import ethtool-5.8-5.el8

This commit is contained in:
CentOS Sources 2020-11-13 10:11:26 +00:00 committed by Andrew Lukoshko
parent 328bbedcd4
commit bf18d6f3bb
8 changed files with 1060 additions and 1 deletions

View File

@ -0,0 +1,117 @@
From 8fa6c3a1bc2536816e961a4ef865c67218683bf2 Mon Sep 17 00:00:00 2001
From: Amit Cohen <amitc@mellanox.com>
Date: Thu, 2 Jul 2020 16:11:09 +0300
Subject: [PATCH 20/26] uapi: linux: update kernel UAPI header files
Add copies of kernel UAPI header files needed for link extended state:
uapi/linux/ethtool.h
uapi/linux/ethtool_netlink.h
The copies are taken from net-next tree,
commit ecc31c60240b ("ethtool: Add link extended state")
Signed-off-by: Amit Cohen <amitc@mellanox.com>
Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
(cherry picked from commit dc46dd315071190b880dba9b48dd4521cf7c133e)
---
uapi/linux/ethtool.h | 70 ++++++++++++++++++++++++++++++++++++
uapi/linux/ethtool_netlink.h | 2 ++
2 files changed, 72 insertions(+)
diff --git a/uapi/linux/ethtool.h b/uapi/linux/ethtool.h
index 355e718a99fd..847ccd0b1fce 100644
--- a/uapi/linux/ethtool.h
+++ b/uapi/linux/ethtool.h
@@ -577,6 +577,76 @@ struct ethtool_pauseparam {
__u32 tx_pause;
};
+/**
+ * enum ethtool_link_ext_state - link extended state
+ */
+enum ethtool_link_ext_state {
+ ETHTOOL_LINK_EXT_STATE_AUTONEG,
+ ETHTOOL_LINK_EXT_STATE_LINK_TRAINING_FAILURE,
+ ETHTOOL_LINK_EXT_STATE_LINK_LOGICAL_MISMATCH,
+ ETHTOOL_LINK_EXT_STATE_BAD_SIGNAL_INTEGRITY,
+ ETHTOOL_LINK_EXT_STATE_NO_CABLE,
+ ETHTOOL_LINK_EXT_STATE_CABLE_ISSUE,
+ ETHTOOL_LINK_EXT_STATE_EEPROM_ISSUE,
+ ETHTOOL_LINK_EXT_STATE_CALIBRATION_FAILURE,
+ ETHTOOL_LINK_EXT_STATE_POWER_BUDGET_EXCEEDED,
+ ETHTOOL_LINK_EXT_STATE_OVERHEAT,
+};
+
+/**
+ * enum ethtool_link_ext_substate_autoneg - more information in addition to
+ * ETHTOOL_LINK_EXT_STATE_AUTONEG.
+ */
+enum ethtool_link_ext_substate_autoneg {
+ ETHTOOL_LINK_EXT_SUBSTATE_AN_NO_PARTNER_DETECTED = 1,
+ ETHTOOL_LINK_EXT_SUBSTATE_AN_ACK_NOT_RECEIVED,
+ ETHTOOL_LINK_EXT_SUBSTATE_AN_NEXT_PAGE_EXCHANGE_FAILED,
+ ETHTOOL_LINK_EXT_SUBSTATE_AN_NO_PARTNER_DETECTED_FORCE_MODE,
+ ETHTOOL_LINK_EXT_SUBSTATE_AN_FEC_MISMATCH_DURING_OVERRIDE,
+ ETHTOOL_LINK_EXT_SUBSTATE_AN_NO_HCD,
+};
+
+/**
+ * enum ethtool_link_ext_substate_link_training - more information in addition to
+ * ETHTOOL_LINK_EXT_STATE_LINK_TRAINING_FAILURE.
+ */
+enum ethtool_link_ext_substate_link_training {
+ ETHTOOL_LINK_EXT_SUBSTATE_LT_KR_FRAME_LOCK_NOT_ACQUIRED = 1,
+ ETHTOOL_LINK_EXT_SUBSTATE_LT_KR_LINK_INHIBIT_TIMEOUT,
+ ETHTOOL_LINK_EXT_SUBSTATE_LT_KR_LINK_PARTNER_DID_NOT_SET_RECEIVER_READY,
+ ETHTOOL_LINK_EXT_SUBSTATE_LT_REMOTE_FAULT,
+};
+
+/**
+ * enum ethtool_link_ext_substate_logical_mismatch - more information in addition
+ * to ETHTOOL_LINK_EXT_STATE_LINK_LOGICAL_MISMATCH.
+ */
+enum ethtool_link_ext_substate_link_logical_mismatch {
+ ETHTOOL_LINK_EXT_SUBSTATE_LLM_PCS_DID_NOT_ACQUIRE_BLOCK_LOCK = 1,
+ ETHTOOL_LINK_EXT_SUBSTATE_LLM_PCS_DID_NOT_ACQUIRE_AM_LOCK,
+ ETHTOOL_LINK_EXT_SUBSTATE_LLM_PCS_DID_NOT_GET_ALIGN_STATUS,
+ ETHTOOL_LINK_EXT_SUBSTATE_LLM_FC_FEC_IS_NOT_LOCKED,
+ ETHTOOL_LINK_EXT_SUBSTATE_LLM_RS_FEC_IS_NOT_LOCKED,
+};
+
+/**
+ * enum ethtool_link_ext_substate_bad_signal_integrity - more information in
+ * addition to ETHTOOL_LINK_EXT_STATE_BAD_SIGNAL_INTEGRITY.
+ */
+enum ethtool_link_ext_substate_bad_signal_integrity {
+ ETHTOOL_LINK_EXT_SUBSTATE_BSI_LARGE_NUMBER_OF_PHYSICAL_ERRORS = 1,
+ ETHTOOL_LINK_EXT_SUBSTATE_BSI_UNSUPPORTED_RATE,
+};
+
+/**
+ * enum ethtool_link_ext_substate_cable_issue - more information in
+ * addition to ETHTOOL_LINK_EXT_STATE_CABLE_ISSUE.
+ */
+enum ethtool_link_ext_substate_cable_issue {
+ ETHTOOL_LINK_EXT_SUBSTATE_CI_UNSUPPORTED_CABLE = 1,
+ ETHTOOL_LINK_EXT_SUBSTATE_CI_CABLE_TEST_FAILURE,
+};
+
#define ETH_GSTRING_LEN 32
/**
diff --git a/uapi/linux/ethtool_netlink.h b/uapi/linux/ethtool_netlink.h
index c1b4d67d35d1..cebdb52e6a05 100644
--- a/uapi/linux/ethtool_netlink.h
+++ b/uapi/linux/ethtool_netlink.h
@@ -237,6 +237,8 @@ enum {
ETHTOOL_A_LINKSTATE_LINK, /* u8 */
ETHTOOL_A_LINKSTATE_SQI, /* u32 */
ETHTOOL_A_LINKSTATE_SQI_MAX, /* u32 */
+ ETHTOOL_A_LINKSTATE_EXT_STATE, /* u8 */
+ ETHTOOL_A_LINKSTATE_EXT_SUBSTATE, /* u8 */
/* add new constants above here */
__ETHTOOL_A_LINKSTATE_CNT,
--
2.26.2

View File

@ -0,0 +1,187 @@
From abc33073ed6d4528d3c951cc719a155a6e1178cd Mon Sep 17 00:00:00 2001
From: Amit Cohen <amitc@mellanox.com>
Date: Thu, 2 Jul 2020 16:11:11 +0300
Subject: [PATCH 21/26] netlink: settings: expand linkstate_reply_cb() to
support link extended state
Print extended state in addition to link state.
In case that extended state is not provided, print state only.
If extended substate is provided in addition to the extended state,
print it also.
Signed-off-by: Amit Cohen <amitc@mellanox.com>
Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
(cherry picked from commit ba6367d2bb32173166b91fbcc053865c99ca7c57)
---
netlink/settings.c | 147 ++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 146 insertions(+), 1 deletion(-)
diff --git a/netlink/settings.c b/netlink/settings.c
index 3a9518a7e12b..75db15e5069c 100644
--- a/netlink/settings.c
+++ b/netlink/settings.c
@@ -565,6 +565,149 @@ int linkinfo_reply_cb(const struct nlmsghdr *nlhdr, void *data)
return MNL_CB_OK;
}
+static const char *get_enum_string(const char *const *string_table, unsigned int n_string_table,
+ unsigned int val)
+{
+ if (val >= n_string_table || !string_table[val])
+ return NULL;
+ else
+ return string_table[val];
+}
+
+static const char *const names_link_ext_state[] = {
+ [ETHTOOL_LINK_EXT_STATE_AUTONEG] = "Autoneg",
+ [ETHTOOL_LINK_EXT_STATE_LINK_TRAINING_FAILURE] = "Link training failure",
+ [ETHTOOL_LINK_EXT_STATE_LINK_LOGICAL_MISMATCH] = "Logical mismatch",
+ [ETHTOOL_LINK_EXT_STATE_BAD_SIGNAL_INTEGRITY] = "Bad signal integrity",
+ [ETHTOOL_LINK_EXT_STATE_NO_CABLE] = "No cable",
+ [ETHTOOL_LINK_EXT_STATE_CABLE_ISSUE] = "Cable issue",
+ [ETHTOOL_LINK_EXT_STATE_EEPROM_ISSUE] = "EEPROM issue",
+ [ETHTOOL_LINK_EXT_STATE_CALIBRATION_FAILURE] = "Calibration failure",
+ [ETHTOOL_LINK_EXT_STATE_POWER_BUDGET_EXCEEDED] = "Power budget exceeded",
+ [ETHTOOL_LINK_EXT_STATE_OVERHEAT] = "Overheat",
+};
+
+static const char *const names_autoneg_link_ext_substate[] = {
+ [ETHTOOL_LINK_EXT_SUBSTATE_AN_NO_PARTNER_DETECTED] =
+ "No partner detected",
+ [ETHTOOL_LINK_EXT_SUBSTATE_AN_ACK_NOT_RECEIVED] =
+ "Ack not received",
+ [ETHTOOL_LINK_EXT_SUBSTATE_AN_NEXT_PAGE_EXCHANGE_FAILED] =
+ "Next page exchange failed",
+ [ETHTOOL_LINK_EXT_SUBSTATE_AN_NO_PARTNER_DETECTED_FORCE_MODE] =
+ "No partner detected during force mode",
+ [ETHTOOL_LINK_EXT_SUBSTATE_AN_FEC_MISMATCH_DURING_OVERRIDE] =
+ "FEC mismatch during override",
+ [ETHTOOL_LINK_EXT_SUBSTATE_AN_NO_HCD] =
+ "No HCD",
+};
+
+static const char *const names_link_training_link_ext_substate[] = {
+ [ETHTOOL_LINK_EXT_SUBSTATE_LT_KR_FRAME_LOCK_NOT_ACQUIRED] =
+ "KR frame lock not acquired",
+ [ETHTOOL_LINK_EXT_SUBSTATE_LT_KR_LINK_INHIBIT_TIMEOUT] =
+ "KR link inhibit timeout",
+ [ETHTOOL_LINK_EXT_SUBSTATE_LT_KR_LINK_PARTNER_DID_NOT_SET_RECEIVER_READY] =
+ "KR Link partner did not set receiver ready",
+ [ETHTOOL_LINK_EXT_SUBSTATE_LT_REMOTE_FAULT] =
+ "Remote side is not ready yet",
+};
+
+static const char *const names_link_logical_mismatch_link_ext_substate[] = {
+ [ETHTOOL_LINK_EXT_SUBSTATE_LLM_PCS_DID_NOT_ACQUIRE_BLOCK_LOCK] =
+ "PCS did not acquire block lock",
+ [ETHTOOL_LINK_EXT_SUBSTATE_LLM_PCS_DID_NOT_ACQUIRE_AM_LOCK] =
+ "PCS did not acquire AM lock",
+ [ETHTOOL_LINK_EXT_SUBSTATE_LLM_PCS_DID_NOT_GET_ALIGN_STATUS] =
+ "PCS did not get align_status",
+ [ETHTOOL_LINK_EXT_SUBSTATE_LLM_FC_FEC_IS_NOT_LOCKED] =
+ "FC FEC is not locked",
+ [ETHTOOL_LINK_EXT_SUBSTATE_LLM_RS_FEC_IS_NOT_LOCKED] =
+ "RS FEC is not locked",
+};
+
+static const char *const names_bad_signal_integrity_link_ext_substate[] = {
+ [ETHTOOL_LINK_EXT_SUBSTATE_BSI_LARGE_NUMBER_OF_PHYSICAL_ERRORS] =
+ "Large number of physical errors",
+ [ETHTOOL_LINK_EXT_SUBSTATE_BSI_UNSUPPORTED_RATE] =
+ "Unsupported rate",
+};
+
+static const char *const names_cable_issue_link_ext_substate[] = {
+ [ETHTOOL_LINK_EXT_SUBSTATE_CI_UNSUPPORTED_CABLE] =
+ "Unsupported cable",
+ [ETHTOOL_LINK_EXT_SUBSTATE_CI_CABLE_TEST_FAILURE] =
+ "Cable test failure",
+};
+
+static const char *link_ext_substate_get(uint8_t link_ext_state_val, uint8_t link_ext_substate_val)
+{
+ switch (link_ext_state_val) {
+ case ETHTOOL_LINK_EXT_STATE_AUTONEG:
+ return get_enum_string(names_autoneg_link_ext_substate,
+ ARRAY_SIZE(names_autoneg_link_ext_substate),
+ link_ext_substate_val);
+ case ETHTOOL_LINK_EXT_STATE_LINK_TRAINING_FAILURE:
+ return get_enum_string(names_link_training_link_ext_substate,
+ ARRAY_SIZE(names_link_training_link_ext_substate),
+ link_ext_substate_val);
+ case ETHTOOL_LINK_EXT_STATE_LINK_LOGICAL_MISMATCH:
+ return get_enum_string(names_link_logical_mismatch_link_ext_substate,
+ ARRAY_SIZE(names_link_logical_mismatch_link_ext_substate),
+ link_ext_substate_val);
+ case ETHTOOL_LINK_EXT_STATE_BAD_SIGNAL_INTEGRITY:
+ return get_enum_string(names_bad_signal_integrity_link_ext_substate,
+ ARRAY_SIZE(names_bad_signal_integrity_link_ext_substate),
+ link_ext_substate_val);
+ case ETHTOOL_LINK_EXT_STATE_CABLE_ISSUE:
+ return get_enum_string(names_cable_issue_link_ext_substate,
+ ARRAY_SIZE(names_cable_issue_link_ext_substate),
+ link_ext_substate_val);
+ default:
+ return NULL;
+ }
+}
+
+static void linkstate_link_ext_substate_print(const struct nlattr *tb[], struct nl_context *nlctx,
+ uint8_t link_ext_state_val)
+{
+ uint8_t link_ext_substate_val;
+ const char *link_ext_substate_str;
+
+ if (!tb[ETHTOOL_A_LINKSTATE_EXT_SUBSTATE])
+ return;
+
+ link_ext_substate_val = mnl_attr_get_u8(tb[ETHTOOL_A_LINKSTATE_EXT_SUBSTATE]);
+
+ link_ext_substate_str = link_ext_substate_get(link_ext_state_val, link_ext_substate_val);
+ if (!link_ext_substate_str)
+ printf(", %u", link_ext_substate_val);
+ else
+ printf(", %s", link_ext_substate_str);
+}
+
+static void linkstate_link_ext_state_print(const struct nlattr *tb[], struct nl_context *nlctx)
+{
+ uint8_t link_ext_state_val;
+ const char *link_ext_state_str;
+
+ if (!tb[ETHTOOL_A_LINKSTATE_EXT_STATE])
+ return;
+
+ link_ext_state_val = mnl_attr_get_u8(tb[ETHTOOL_A_LINKSTATE_EXT_STATE]);
+
+ link_ext_state_str = get_enum_string(names_link_ext_state,
+ ARRAY_SIZE(names_link_ext_state),
+ link_ext_state_val);
+ if (!link_ext_state_str)
+ printf(" (%u", link_ext_state_val);
+ else
+ printf(" (%s", link_ext_state_str);
+
+ linkstate_link_ext_substate_print(tb, nlctx, link_ext_state_val);
+ printf(")");
+}
+
int linkstate_reply_cb(const struct nlmsghdr *nlhdr, void *data)
{
const struct nlattr *tb[ETHTOOL_A_LINKSTATE_MAX + 1] = {};
@@ -585,7 +728,9 @@ int linkstate_reply_cb(const struct nlmsghdr *nlhdr, void *data)
uint8_t val = mnl_attr_get_u8(tb[ETHTOOL_A_LINKSTATE_LINK]);
print_banner(nlctx);
- printf("\tLink detected: %s\n", val ? "yes" : "no");
+ printf("\tLink detected: %s", val ? "yes" : "no");
+ linkstate_link_ext_state_print(tb, nlctx);
+ printf("\n");
}
if (tb[ETHTOOL_A_LINKSTATE_SQI]) {
--
2.26.2

View File

@ -0,0 +1,126 @@
From 15e57173470b0929fd649bc7b0376d41c786ddbe Mon Sep 17 00:00:00 2001
From: Jakub Kicinski <kuba@kernel.org>
Date: Sun, 18 Oct 2020 14:31:49 -0700
Subject: [PATCH 22/26] netlink: prepare for more per-op info
We stored an array of op flags, to check if operations are
supported. Make that array a structure rather than plain
uint32_t in preparation for storing more state.
v3: new patch
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
(cherry picked from commit 8d36270be3c06b99eba281ccf341ebfab555c6b6)
---
netlink/netlink.c | 25 +++++++++++++------------
netlink/netlink.h | 6 +++++-
2 files changed, 18 insertions(+), 13 deletions(-)
diff --git a/netlink/netlink.c b/netlink/netlink.c
index e42d57076a4b..86dc1efdf5ce 100644
--- a/netlink/netlink.c
+++ b/netlink/netlink.c
@@ -120,19 +120,19 @@ bool netlink_cmd_check(struct cmd_context *ctx, unsigned int cmd,
nlctx->wildcard_unsupported = true;
return true;
}
- if (!nlctx->ops_flags) {
+ if (!nlctx->ops_info) {
nlctx->ioctl_fallback = true;
return false;
}
- if (cmd > ETHTOOL_MSG_USER_MAX || !nlctx->ops_flags[cmd]) {
+ if (cmd > ETHTOOL_MSG_USER_MAX || !nlctx->ops_info[cmd].op_flags) {
nlctx->ioctl_fallback = true;
return true;
}
- if (is_dump && !(nlctx->ops_flags[cmd] & GENL_CMD_CAP_DUMP))
+ if (is_dump && !(nlctx->ops_info[cmd].op_flags & GENL_CMD_CAP_DUMP))
nlctx->wildcard_unsupported = true;
- return !(nlctx->ops_flags[cmd] & cap);
+ return !(nlctx->ops_info[cmd].op_flags & cap);
}
/* initialization */
@@ -140,12 +140,12 @@ bool netlink_cmd_check(struct cmd_context *ctx, unsigned int cmd,
static int genl_read_ops(struct nl_context *nlctx,
const struct nlattr *ops_attr)
{
+ struct nl_op_info *ops_info;
struct nlattr *op_attr;
- uint32_t *ops_flags;
int ret;
- ops_flags = calloc(__ETHTOOL_MSG_USER_CNT, sizeof(ops_flags[0]));
- if (!ops_flags)
+ ops_info = calloc(__ETHTOOL_MSG_USER_CNT, sizeof(ops_info[0]));
+ if (!ops_info)
return -ENOMEM;
mnl_attr_for_each_nested(op_attr, ops_attr) {
@@ -163,13 +163,14 @@ static int genl_read_ops(struct nl_context *nlctx,
if (op_id >= __ETHTOOL_MSG_USER_CNT)
continue;
- ops_flags[op_id] = mnl_attr_get_u32(tb[CTRL_ATTR_OP_FLAGS]);
+ ops_info[op_id].op_flags =
+ mnl_attr_get_u32(tb[CTRL_ATTR_OP_FLAGS]);
}
- nlctx->ops_flags = ops_flags;
+ nlctx->ops_info = ops_info;
return 0;
err:
- free(ops_flags);
+ free(ops_info);
return ret;
}
@@ -273,7 +274,7 @@ int netlink_init(struct cmd_context *ctx)
out_nlsk:
nlsock_done(nlctx->ethnl_socket);
out_free:
- free(nlctx->ops_flags);
+ free(nlctx->ops_info);
free(nlctx);
return ret;
}
@@ -283,7 +284,7 @@ static void netlink_done(struct cmd_context *ctx)
if (!ctx->nlctx)
return;
- free(ctx->nlctx->ops_flags);
+ free(ctx->nlctx->ops_info);
free(ctx->nlctx);
ctx->nlctx = NULL;
cleanup_all_strings();
diff --git a/netlink/netlink.h b/netlink/netlink.h
index dd4a02bcc916..61a072db8ed9 100644
--- a/netlink/netlink.h
+++ b/netlink/netlink.h
@@ -25,6 +25,10 @@ enum link_mode_class {
LM_CLASS_FEC,
};
+struct nl_op_info {
+ uint32_t op_flags;
+};
+
struct nl_context {
struct cmd_context *ctx;
void *cmd_private;
@@ -34,7 +38,7 @@ struct nl_context {
unsigned int suppress_nlerr;
uint16_t ethnl_fam;
uint32_t ethnl_mongrp;
- uint32_t *ops_flags;
+ struct nl_op_info *ops_info;
struct nl_socket *ethnl_socket;
struct nl_socket *ethnl2_socket;
struct nl_socket *rtnl_socket;
--
2.26.2

View File

@ -0,0 +1,53 @@
From ef1675823905ff09cb5e551700a124d0133648b7 Mon Sep 17 00:00:00 2001
From: Michal Kubecek <mkubecek@suse.cz>
Date: Mon, 9 Nov 2020 13:30:54 +0100
Subject: [PATCH 23/26] netlink: fix use after free in netlink_run_handler()
Valgrind detected use after free in netlink_run_handler(): some members of
struct nl_context are accessed after the netlink context is freed by
netlink_done(). Use local variables to store the two flags and check them
instead.
Fixes: 6c19c0d559c8 ("netlink: use genetlink ops information to decide about fallback")
Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
(cherry picked from commit 29b38ea218bd978d1950e12cc24da98215a1eeef)
---
netlink/netlink.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/netlink/netlink.c b/netlink/netlink.c
index 86dc1efdf5ce..2a12bb8b1759 100644
--- a/netlink/netlink.c
+++ b/netlink/netlink.c
@@ -303,6 +303,7 @@ void netlink_run_handler(struct cmd_context *ctx, nl_func_t nlfunc,
bool no_fallback)
{
bool wildcard = ctx->devname && !strcmp(ctx->devname, WILDCARD_DEVNAME);
+ bool wildcard_unsupported, ioctl_fallback;
struct nl_context *nlctx;
const char *reason;
int ret;
@@ -324,14 +325,17 @@ void netlink_run_handler(struct cmd_context *ctx, nl_func_t nlfunc,
nlctx = ctx->nlctx;
ret = nlfunc(ctx);
+ wildcard_unsupported = nlctx->wildcard_unsupported;
+ ioctl_fallback = nlctx->ioctl_fallback;
netlink_done(ctx);
- if (no_fallback || ret != -EOPNOTSUPP || !nlctx->ioctl_fallback) {
- if (nlctx->wildcard_unsupported)
+
+ if (no_fallback || ret != -EOPNOTSUPP || !ioctl_fallback) {
+ if (wildcard_unsupported)
fprintf(stderr, "%s\n",
"subcommand does not support wildcard dump");
exit(ret >= 0 ? ret : 1);
}
- if (nlctx->wildcard_unsupported)
+ if (wildcard_unsupported)
reason = "subcommand does not support wildcard dump";
else
reason = "kernel netlink support for subcommand missing";
--
2.26.2

View File

@ -0,0 +1,64 @@
From 5fad40a007b61092161d1e4fd0ffbbc3e7b8ba6c Mon Sep 17 00:00:00 2001
From: Michal Kubecek <mkubecek@suse.cz>
Date: Mon, 9 Nov 2020 13:30:57 +0100
Subject: [PATCH 24/26] netlink: fix leaked instances of struct nl_socket
Valgrind detected memory leaks caused by missing cleanup of netlink
context's ethnl_socket, ethnl2_socket and rtnl_socket. Also, contrary to
its description, nlsock_done() does not free struct nl_socket itself.
Fix nlsock_done() to free the structure and use it to dispose of sockets
pointed to by struct nl_context members.
Fixes: 50efb3cdd2bb ("netlink: netlink socket wrapper and helpers")
Fixes: 87307c30724d ("netlink: initialize ethtool netlink socket")
Fixes: 7f3585b22a4b ("netlink: add handler for permaddr (-P)")
Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
(cherry picked from commit d85f57499d75da5c98b73652488f3f62c6f6d8ea)
---
netlink/netlink.c | 11 ++++++++---
netlink/nlsock.c | 3 +++
2 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/netlink/netlink.c b/netlink/netlink.c
index 2a12bb8b1759..5677274c2fce 100644
--- a/netlink/netlink.c
+++ b/netlink/netlink.c
@@ -281,11 +281,16 @@ out_free:
static void netlink_done(struct cmd_context *ctx)
{
- if (!ctx->nlctx)
+ struct nl_context *nlctx = ctx->nlctx;
+
+ if (!nlctx)
return;
- free(ctx->nlctx->ops_info);
- free(ctx->nlctx);
+ nlsock_done(nlctx->ethnl_socket);
+ nlsock_done(nlctx->ethnl2_socket);
+ nlsock_done(nlctx->rtnl_socket);
+ free(nlctx->ops_info);
+ free(nlctx);
ctx->nlctx = NULL;
cleanup_all_strings();
}
diff --git a/netlink/nlsock.c b/netlink/nlsock.c
index ef31d8c33b29..0ec2738d81d2 100644
--- a/netlink/nlsock.c
+++ b/netlink/nlsock.c
@@ -395,8 +395,11 @@ out_msgbuff:
*/
void nlsock_done(struct nl_socket *nlsk)
{
+ if (!nlsk)
+ return;
if (nlsk->sk)
mnl_socket_close(nlsk->sk);
msgbuff_done(&nlsk->msgbuff);
memset(nlsk, '\0', sizeof(*nlsk));
+ free(nlsk);
}
--
2.26.2

View File

@ -0,0 +1,301 @@
From fc5f2a6bb2911a951bf5a1364dc5732e521d735a Mon Sep 17 00:00:00 2001
From: Michal Kubecek <mkubecek@suse.cz>
Date: Mon, 9 Nov 2020 14:29:56 +0100
Subject: [PATCH 25/26] netlink: do not send messages and process replies in
nl_parser()
When called with group_style = PARSER_GROUP_MSG, nl_parser() not only
parses the command line and composes the messages but also sends them to
kernel and processes the replies. This is inconsistent with other modes and
also impractical as it takes the control over the process from caller where
it belongs.
Modify nl_parser() to pass composed messages back to caller (which is only
nl_sset() at the moment) and let it send requests and process replies. This
will be needed for an upcoming backward compatibility patch which will need
to inspect and possibly modify one of the composed messages.
Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
(cherry picked from commit acd9730d1e794f85caf1192fe8788876e6f96305)
---
netlink/cable_test.c | 2 +-
netlink/channels.c | 2 +-
netlink/coalesce.c | 2 +-
netlink/eee.c | 2 +-
netlink/parser.c | 43 ++++++++++++++++++++++++++++---------------
netlink/parser.h | 3 ++-
netlink/pause.c | 2 +-
netlink/rings.c | 2 +-
netlink/settings.c | 35 ++++++++++++++++++++++++++++++-----
9 files changed, 66 insertions(+), 27 deletions(-)
diff --git a/netlink/cable_test.c b/netlink/cable_test.c
index d39b7d82efb0..e05b67c4e231 100644
--- a/netlink/cable_test.c
+++ b/netlink/cable_test.c
@@ -574,7 +574,7 @@ int nl_cable_test_tdr(struct cmd_context *ctx)
ctx->devname, 0))
return -EMSGSIZE;
- ret = nl_parser(nlctx, tdr_params, NULL, PARSER_GROUP_NEST);
+ ret = nl_parser(nlctx, tdr_params, NULL, PARSER_GROUP_NEST, NULL);
if (ret < 0)
return ret;
diff --git a/netlink/channels.c b/netlink/channels.c
index c6002ceeb121..894c74bcc11a 100644
--- a/netlink/channels.c
+++ b/netlink/channels.c
@@ -126,7 +126,7 @@ int nl_schannels(struct cmd_context *ctx)
ctx->devname, 0))
return -EMSGSIZE;
- ret = nl_parser(nlctx, schannels_params, NULL, PARSER_GROUP_NONE);
+ ret = nl_parser(nlctx, schannels_params, NULL, PARSER_GROUP_NONE, NULL);
if (ret < 0)
return 1;
diff --git a/netlink/coalesce.c b/netlink/coalesce.c
index 65f75cf9a8dd..0223f8e3484e 100644
--- a/netlink/coalesce.c
+++ b/netlink/coalesce.c
@@ -254,7 +254,7 @@ int nl_scoalesce(struct cmd_context *ctx)
ctx->devname, 0))
return -EMSGSIZE;
- ret = nl_parser(nlctx, scoalesce_params, NULL, PARSER_GROUP_NONE);
+ ret = nl_parser(nlctx, scoalesce_params, NULL, PARSER_GROUP_NONE, NULL);
if (ret < 0)
return 1;
diff --git a/netlink/eee.c b/netlink/eee.c
index d3135b2094a4..04d8f0bbe3fc 100644
--- a/netlink/eee.c
+++ b/netlink/eee.c
@@ -174,7 +174,7 @@ int nl_seee(struct cmd_context *ctx)
ctx->devname, 0))
return -EMSGSIZE;
- ret = nl_parser(nlctx, seee_params, NULL, PARSER_GROUP_NONE);
+ ret = nl_parser(nlctx, seee_params, NULL, PARSER_GROUP_NONE, NULL);
if (ret < 0)
return 1;
diff --git a/netlink/parser.c b/netlink/parser.c
index 3b25f5d5a88e..c2eae93efb69 100644
--- a/netlink/parser.c
+++ b/netlink/parser.c
@@ -920,7 +920,7 @@ static void __parser_set(uint64_t *map, unsigned int idx)
}
struct tmp_buff {
- struct nl_msg_buff msgbuff;
+ struct nl_msg_buff *msgbuff;
unsigned int id;
unsigned int orig_len;
struct tmp_buff *next;
@@ -951,7 +951,12 @@ static struct tmp_buff *tmp_buff_find_or_create(struct tmp_buff **phead,
if (!new_buff)
return NULL;
new_buff->id = id;
- msgbuff_init(&new_buff->msgbuff);
+ new_buff->msgbuff = malloc(sizeof(*new_buff->msgbuff));
+ if (!new_buff->msgbuff) {
+ free(new_buff);
+ return NULL;
+ }
+ msgbuff_init(new_buff->msgbuff);
new_buff->next = NULL;
*pbuff = new_buff;
@@ -965,7 +970,10 @@ static void tmp_buff_destroy(struct tmp_buff *head)
while (buff) {
next = buff->next;
- msgbuff_done(&buff->msgbuff);
+ if (buff->msgbuff) {
+ msgbuff_done(buff->msgbuff);
+ free(buff->msgbuff);
+ }
free(buff);
buff = next;
}
@@ -980,13 +988,22 @@ static void tmp_buff_destroy(struct tmp_buff *head)
* param_parser::offset)
* @group_style: defines if identifiers in .group represent separate messages,
* nested attributes or are not allowed
+ * @msgbuffs: (only used for @group_style = PARSER_GROUP_MSG) array to store
+ * pointers to composed messages; caller must make sure this
+ * array is sufficient, i.e. that it has at least as many entries
+ * as the number of different .group values in params array;
+ * entries are filled from the start, remaining entries are not
+ * modified; caller should zero initialize the array before
+ * calling nl_parser()
*/
int nl_parser(struct nl_context *nlctx, const struct param_parser *params,
- void *dest, enum parser_group_style group_style)
+ void *dest, enum parser_group_style group_style,
+ struct nl_msg_buff **msgbuffs)
{
struct nl_socket *nlsk = nlctx->ethnl_socket;
const struct param_parser *parser;
struct tmp_buff *buffs = NULL;
+ unsigned int n_msgbuffs = 0;
struct tmp_buff *buff;
unsigned int n_params;
uint64_t *params_seen;
@@ -1004,7 +1021,7 @@ int nl_parser(struct nl_context *nlctx, const struct param_parser *params,
buff = tmp_buff_find_or_create(&buffs, parser->group);
if (!buff)
goto out_free_buffs;
- msgbuff = &buff->msgbuff;
+ msgbuff = buff->msgbuff;
ret = msg_init(nlctx, msgbuff, parser->group,
NLM_F_REQUEST | NLM_F_ACK);
if (ret < 0)
@@ -1013,7 +1030,7 @@ int nl_parser(struct nl_context *nlctx, const struct param_parser *params,
switch (group_style) {
case PARSER_GROUP_NEST:
ret = -EMSGSIZE;
- nest = ethnla_nest_start(&buff->msgbuff, parser->group);
+ nest = ethnla_nest_start(buff->msgbuff, parser->group);
if (!nest)
goto out_free_buffs;
break;
@@ -1062,7 +1079,7 @@ int nl_parser(struct nl_context *nlctx, const struct param_parser *params,
buff = NULL;
if (parser->group)
buff = tmp_buff_find(buffs, parser->group);
- msgbuff = buff ? &buff->msgbuff : &nlsk->msgbuff;
+ msgbuff = buff ? buff->msgbuff : &nlsk->msgbuff;
param_dest = dest ? ((char *)dest + parser->dest_offset) : NULL;
ret = parser->handler(nlctx, parser->type, parser->handler_data,
@@ -1074,12 +1091,12 @@ int nl_parser(struct nl_context *nlctx, const struct param_parser *params,
if (group_style == PARSER_GROUP_MSG) {
ret = -EOPNOTSUPP;
for (buff = buffs; buff; buff = buff->next)
- if (msgbuff_len(&buff->msgbuff) > buff->orig_len &&
+ if (msgbuff_len(buff->msgbuff) > buff->orig_len &&
netlink_cmd_check(nlctx->ctx, buff->id, false))
goto out_free;
}
for (buff = buffs; buff; buff = buff->next) {
- struct nl_msg_buff *msgbuff = &buff->msgbuff;
+ struct nl_msg_buff *msgbuff = buff->msgbuff;
if (group_style == PARSER_GROUP_NONE ||
msgbuff_len(msgbuff) == buff->orig_len)
@@ -1092,12 +1109,8 @@ int nl_parser(struct nl_context *nlctx, const struct param_parser *params,
goto out_free;
break;
case PARSER_GROUP_MSG:
- ret = nlsock_sendmsg(nlsk, msgbuff);
- if (ret < 0)
- goto out_free;
- ret = nlsock_process_reply(nlsk, nomsg_reply_cb, NULL);
- if (ret < 0)
- goto out_free;
+ msgbuffs[n_msgbuffs++] = msgbuff;
+ buff->msgbuff = NULL;
break;
default:
break;
diff --git a/netlink/parser.h b/netlink/parser.h
index fd55bc768d42..28f26ccc2a1c 100644
--- a/netlink/parser.h
+++ b/netlink/parser.h
@@ -143,6 +143,7 @@ int nl_parse_char_bitset(struct nl_context *nlctx, uint16_t type,
/* main entry point called to parse the command line */
int nl_parser(struct nl_context *nlctx, const struct param_parser *params,
- void *dest, enum parser_group_style group_style);
+ void *dest, enum parser_group_style group_style,
+ struct nl_msg_buff **msgbuffs);
#endif /* ETHTOOL_NETLINK_PARSER_H__ */
diff --git a/netlink/pause.c b/netlink/pause.c
index 7b6b3a1d2c10..048320b123d2 100644
--- a/netlink/pause.c
+++ b/netlink/pause.c
@@ -208,7 +208,7 @@ int nl_spause(struct cmd_context *ctx)
ctx->devname, 0))
return -EMSGSIZE;
- ret = nl_parser(nlctx, spause_params, NULL, PARSER_GROUP_NONE);
+ ret = nl_parser(nlctx, spause_params, NULL, PARSER_GROUP_NONE, NULL);
if (ret < 0)
return 1;
diff --git a/netlink/rings.c b/netlink/rings.c
index 4061520212d5..b8c458fce25f 100644
--- a/netlink/rings.c
+++ b/netlink/rings.c
@@ -126,7 +126,7 @@ int nl_sring(struct cmd_context *ctx)
ctx->devname, 0))
return -EMSGSIZE;
- ret = nl_parser(nlctx, sring_params, NULL, PARSER_GROUP_NONE);
+ ret = nl_parser(nlctx, sring_params, NULL, PARSER_GROUP_NONE, NULL);
if (ret < 0)
return 1;
diff --git a/netlink/settings.c b/netlink/settings.c
index 75db15e5069c..fac192e2fbb7 100644
--- a/netlink/settings.c
+++ b/netlink/settings.c
@@ -1108,9 +1108,16 @@ static const struct param_parser sset_params[] = {
{}
};
+/* Maximum number of request messages sent to kernel; must be equal to the
+ * number of different .group values in sset_params[] array.
+ */
+#define SSET_MAX_MSGS 4
+
int nl_sset(struct cmd_context *ctx)
{
+ struct nl_msg_buff *msgbuffs[SSET_MAX_MSGS] = {};
struct nl_context *nlctx = ctx->nlctx;
+ unsigned int i;
int ret;
nlctx->cmd = "-s";
@@ -1118,11 +1125,29 @@ int nl_sset(struct cmd_context *ctx)
nlctx->argc = ctx->argc;
nlctx->devname = ctx->devname;
- ret = nl_parser(nlctx, sset_params, NULL, PARSER_GROUP_MSG);
- if (ret < 0)
- return 1;
+ ret = nl_parser(nlctx, sset_params, NULL, PARSER_GROUP_MSG, msgbuffs);
+ if (ret < 0) {
+ ret = 1;
+ goto out_free;
+ }
+
+ for (i = 0; i < SSET_MAX_MSGS && msgbuffs[i]; i++) {
+ struct nl_socket *nlsk = nlctx->ethnl_socket;
- if (ret == 0)
- return 0;
+ ret = nlsock_sendmsg(nlsk, msgbuffs[i]);
+ if (ret < 0)
+ goto out_free;
+ ret = nlsock_process_reply(nlsk, nomsg_reply_cb, NULL);
+ if (ret < 0)
+ goto out_free;
+ }
+
+out_free:
+ for (i = 0; i < SSET_MAX_MSGS && msgbuffs[i]; i++) {
+ msgbuff_done(msgbuffs[i]);
+ free(msgbuffs[i]);
+ }
+ if (ret >= 0)
+ return ret;
return nlctx->exit_code ?: 75;
}
--
2.26.2

View File

@ -0,0 +1,191 @@
From f16bc54fe82b9129d6852273d02e044b9cb28789 Mon Sep 17 00:00:00 2001
From: Ido Schimmel <idosch@nvidia.com>
Date: Mon, 9 Nov 2020 14:29:59 +0100
Subject: [PATCH 26/26] ethtool: Improve compatibility between netlink and
ioctl interfaces
With the ioctl interface, when autoneg is enabled, but without
specifying speed, duplex or link modes, the advertised link modes are
set to the supported link modes by the ethtool user space utility.
This does not happen when using the netlink interface. Fix this
incompatibility problem by having ethtool query the supported link modes
from the kernel and advertise all the "real" ones when only "autoneg on"
is specified.
Before:
Settings for eth0:
Supported ports: [ TP ]
Supported link modes: 10baseT/Half 10baseT/Full
100baseT/Half 100baseT/Full
1000baseT/Full
Supported pause frame use: No
Supports auto-negotiation: Yes
Supported FEC modes: Not reported
Advertised link modes: 100baseT/Half 100baseT/Full
Advertised pause frame use: No
Advertised auto-negotiation: Yes
Advertised FEC modes: Not reported
Speed: 1000Mb/s
Duplex: Full
Auto-negotiation: on
Port: Twisted Pair
PHYAD: 0
Transceiver: internal
MDI-X: off (auto)
Supports Wake-on: umbg
Wake-on: d
Current message level: 0x00000007 (7)
drv probe link
Link detected: yes
After:
Settings for eth0:
Supported ports: [ TP ]
Supported link modes: 10baseT/Half 10baseT/Full
100baseT/Half 100baseT/Full
1000baseT/Full
Supported pause frame use: No
Supports auto-negotiation: Yes
Supported FEC modes: Not reported
Advertised link modes: 10baseT/Half 10baseT/Full
100baseT/Half 100baseT/Full
1000baseT/Full
Advertised pause frame use: No
Advertised auto-negotiation: Yes
Advertised FEC modes: Not reported
Speed: 1000Mb/s
Duplex: Full
Auto-negotiation: on
Port: Twisted Pair
PHYAD: 0
Transceiver: internal
MDI-X: on (auto)
Supports Wake-on: umbg
Wake-on: d
Current message level: 0x00000007 (7)
drv probe link
Link detected: yes
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
(cherry picked from commit 124a3c06d1c34b125d84a9eb312fddd365bb7bf6)
---
netlink/settings.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 92 insertions(+)
diff --git a/netlink/settings.c b/netlink/settings.c
index fac192e2fbb7..01c1d38d323f 100644
--- a/netlink/settings.c
+++ b/netlink/settings.c
@@ -1113,6 +1113,93 @@ static const struct param_parser sset_params[] = {
*/
#define SSET_MAX_MSGS 4
+static int linkmodes_reply_advert_all_cb(const struct nlmsghdr *nlhdr,
+ void *data)
+{
+ const struct nlattr *tb[ETHTOOL_A_LINKMODES_MAX + 1] = {};
+ DECLARE_ATTR_TB_INFO(tb);
+ struct nl_msg_buff *req_msgbuff = data;
+ const struct nlattr *ours_attr;
+ struct nlattr *req_bitset;
+ uint32_t *supported_modes;
+ unsigned int modes_count;
+ unsigned int i;
+ int ret;
+
+ ret = mnl_attr_parse(nlhdr, GENL_HDRLEN, attr_cb, &tb_info);
+ if (ret < 0)
+ return MNL_CB_ERROR;
+ ours_attr = tb[ETHTOOL_A_LINKMODES_OURS];
+ if (!ours_attr)
+ return MNL_CB_ERROR;
+ modes_count = bitset_get_count(tb[ETHTOOL_A_LINKMODES_OURS], &ret);
+ if (ret < 0)
+ return MNL_CB_ERROR;
+ supported_modes = get_compact_bitset_mask(tb[ETHTOOL_A_LINKMODES_OURS]);
+ if (!supported_modes)
+ return MNL_CB_ERROR;
+
+ /* keep only "real" link modes */
+ for (i = 0; i < modes_count; i++)
+ if (!lm_class_match(i, LM_CLASS_REAL))
+ supported_modes[i / 32] &= ~((uint32_t)1 << (i % 32));
+
+ req_bitset = ethnla_nest_start(req_msgbuff, ETHTOOL_A_LINKMODES_OURS);
+ if (!req_bitset)
+ return MNL_CB_ERROR;
+
+ if (ethnla_put_u32(req_msgbuff, ETHTOOL_A_BITSET_SIZE, modes_count) ||
+ ethnla_put(req_msgbuff, ETHTOOL_A_BITSET_VALUE,
+ DIV_ROUND_UP(modes_count, 32) * sizeof(uint32_t),
+ supported_modes) ||
+ ethnla_put(req_msgbuff, ETHTOOL_A_BITSET_MASK,
+ DIV_ROUND_UP(modes_count, 32) * sizeof(uint32_t),
+ supported_modes)) {
+ ethnla_nest_cancel(req_msgbuff, req_bitset);
+ return MNL_CB_ERROR;
+ }
+
+ ethnla_nest_end(req_msgbuff, req_bitset);
+ return MNL_CB_OK;
+}
+
+/* For compatibility reasons with ioctl-based ethtool, when "autoneg on" is
+ * specified without "advertise", "speed" and "duplex", we need to query the
+ * supported link modes from the kernel and advertise all the "real" ones.
+ */
+static int nl_sset_compat_linkmodes(struct nl_context *nlctx,
+ struct nl_msg_buff *msgbuff)
+{
+ const struct nlattr *tb[ETHTOOL_A_LINKMODES_MAX + 1] = {};
+ DECLARE_ATTR_TB_INFO(tb);
+ struct nl_socket *nlsk = nlctx->ethnl_socket;
+ int ret;
+
+ ret = mnl_attr_parse(msgbuff->nlhdr, GENL_HDRLEN, attr_cb, &tb_info);
+ if (ret < 0)
+ return ret;
+ if (!tb[ETHTOOL_A_LINKMODES_AUTONEG] || tb[ETHTOOL_A_LINKMODES_OURS] ||
+ tb[ETHTOOL_A_LINKMODES_SPEED] || tb[ETHTOOL_A_LINKMODES_DUPLEX])
+ return 0;
+ if (!mnl_attr_get_u8(tb[ETHTOOL_A_LINKMODES_AUTONEG]))
+ return 0;
+
+ /* all conditions satisfied, create ETHTOOL_A_LINKMODES_OURS */
+ if (netlink_cmd_check(nlctx->ctx, ETHTOOL_MSG_LINKMODES_GET, false) ||
+ netlink_cmd_check(nlctx->ctx, ETHTOOL_MSG_LINKMODES_SET, false))
+ return -EOPNOTSUPP;
+ ret = nlsock_prep_get_request(nlsk, ETHTOOL_MSG_LINKMODES_GET,
+ ETHTOOL_A_LINKMODES_HEADER,
+ ETHTOOL_FLAG_COMPACT_BITSETS);
+ if (ret < 0)
+ return ret;
+ ret = nlsock_sendmsg(nlsk, NULL);
+ if (ret < 0)
+ return ret;
+ return nlsock_process_reply(nlsk, linkmodes_reply_advert_all_cb,
+ msgbuff);
+}
+
int nl_sset(struct cmd_context *ctx)
{
struct nl_msg_buff *msgbuffs[SSET_MAX_MSGS] = {};
@@ -1134,6 +1221,11 @@ int nl_sset(struct cmd_context *ctx)
for (i = 0; i < SSET_MAX_MSGS && msgbuffs[i]; i++) {
struct nl_socket *nlsk = nlctx->ethnl_socket;
+ if (msgbuffs[i]->genlhdr->cmd == ETHTOOL_MSG_LINKMODES_SET) {
+ ret = nl_sset_compat_linkmodes(nlctx, msgbuffs[i]);
+ if (ret < 0)
+ goto out_free;
+ }
ret = nlsock_sendmsg(nlsk, msgbuffs[i]);
if (ret < 0)
goto out_free;
--
2.26.2

View File

@ -1,7 +1,7 @@
Name: ethtool
Epoch: 2
Version: 5.8
Release: 3%{?dist}
Release: 5%{?dist}
Summary: Settings tool for Ethernet NICs
License: GPLv2
Group: Applications/System
@ -26,6 +26,13 @@ Patch16: 0016-netlink-return-ENOMEM-when-calloc-fails.patch
Patch17: 0017-netlink-fix-memory-leak.patch
Patch18: 0018-fix-memory-leaks-in-do_sfeatures.patch
Patch19: 0019-netlink-fix-copy-paste-error-in-rtm_link_summary.patch
Patch20: 0020-uapi-linux-update-kernel-UAPI-header-files.patch
Patch21: 0021-netlink-settings-expand-linkstate_reply_cb-to-suppor.patch
Patch22: 0022-netlink-prepare-for-more-per-op-info.patch
Patch23: 0023-netlink-fix-use-after-free-in-netlink_run_handler.patch
Patch24: 0024-netlink-fix-leaked-instances-of-struct-nl_socket.patch
Patch25: 0025-netlink-do-not-send-messages-and-process-replies-in-.patch
Patch26: 0026-ethtool-Improve-compatibility-between-netlink-and-io.patch
BuildRequires: libmnl-devel
Conflicts: filesystem < 3
@ -55,6 +62,13 @@ network devices, especially of Ethernet devices.
%patch17 -p1
%patch18 -p1
%patch19 -p1
%patch20 -p1
%patch21 -p1
%patch22 -p1
%patch23 -p1
%patch24 -p1
%patch25 -p1
%patch26 -p1
%build
%configure
@ -71,6 +85,12 @@ make DESTDIR=%{buildroot} INSTALL='install -p' install
%{_datadir}/bash-completion/completions/ethtool
%changelog
* Thu Nov 12 2020 Ivan Vecera <ivecera@redhat.com> - 2:5.8-5
- Fixed a regression
* Fri Nov 06 2020 Ivan Vecera <ivecera@redhat.com> - 2:5.8-4
- Added support for extended link state reporting
* Fri Sep 25 2020 Ivan Vecera <ivecera@redhat.com> - 2:5.8-3
- Fixed memory leak