From 3580dfe517aa7ec031b1d93e876f4469c3b1fb28 Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Mon, 24 Mar 2025 21:16:47 +0100 Subject: [PATCH] platform: replace EEE ethtool ioctl calls with netlink --- src/libnm-platform/nm-linux-platform.c | 24 ++++++ src/libnm-platform/nm-platform.c | 5 +- src/libnm-platform/nm-platform.h | 2 + src/libnm-platform/nmp-ethtool-ioctl.c | 60 -------------- src/libnm-platform/nmp-ethtool-ioctl.h | 4 - src/libnm-platform/nmp-ethtool.c | 105 +++++++++++++++++++++++++ src/libnm-platform/nmp-ethtool.h | 9 +++ 7 files changed, 143 insertions(+), 66 deletions(-) diff --git a/src/libnm-platform/nm-linux-platform.c b/src/libnm-platform/nm-linux-platform.c index 8746de7f8f..5fe0ff036d 100644 --- a/src/libnm-platform/nm-linux-platform.c +++ b/src/libnm-platform/nm-linux-platform.c @@ -11855,6 +11855,28 @@ ethtool_set_pause(NMPlatform *platform, int ifindex, const NMEthtoolPauseState * pause); } +static gboolean +ethtool_get_eee(NMPlatform *platform, int ifindex, NMEthtoolEEEState *eee) +{ + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); + + return nmp_ethtool_get_eee(priv->sk_genl_sync, + genl_get_family_id(platform, NMP_GENL_FAMILY_TYPE_ETHTOOL), + ifindex, + eee); +} + +static gboolean +ethtool_set_eee(NMPlatform *platform, int ifindex, const NMEthtoolEEEState *eee) +{ + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); + + return nmp_ethtool_set_eee(priv->sk_genl_sync, + genl_get_family_id(platform, NMP_GENL_FAMILY_TYPE_ETHTOOL), + ifindex, + eee); +} + /*****************************************************************************/ static void @@ -12357,4 +12379,6 @@ nm_linux_platform_class_init(NMLinuxPlatformClass *klass) platform_class->ethtool_set_pause = ethtool_set_pause; platform_class->ethtool_get_pause = ethtool_get_pause; + platform_class->ethtool_set_eee = ethtool_set_eee; + platform_class->ethtool_get_eee = ethtool_get_eee; } diff --git a/src/libnm-platform/nm-platform.c b/src/libnm-platform/nm-platform.c index cfd1dab597..47db1c40be 100644 --- a/src/libnm-platform/nm-platform.c +++ b/src/libnm-platform/nm-platform.c @@ -3737,7 +3737,7 @@ nm_platform_ethtool_get_eee(NMPlatform *self, int ifindex, NMEthtoolEEEState *ee g_return_val_if_fail(ifindex > 0, FALSE); g_return_val_if_fail(eee, FALSE); - return nmp_ethtool_ioctl_get_eee(ifindex, eee); + return klass->ethtool_get_eee(self, ifindex, eee); } gboolean @@ -3746,8 +3746,9 @@ nm_platform_ethtool_set_eee(NMPlatform *self, int ifindex, const NMEthtoolEEESta _CHECK_SELF_NETNS(self, klass, netns, FALSE); g_return_val_if_fail(ifindex > 0, FALSE); + g_return_val_if_fail(eee, FALSE); - return nmp_ethtool_ioctl_set_eee(ifindex, eee); + return klass->ethtool_set_eee(self, ifindex, eee); } /*****************************************************************************/ diff --git a/src/libnm-platform/nm-platform.h b/src/libnm-platform/nm-platform.h index aacd323cf5..405a2d012d 100644 --- a/src/libnm-platform/nm-platform.h +++ b/src/libnm-platform/nm-platform.h @@ -1348,6 +1348,8 @@ typedef struct { gboolean (*ethtool_get_pause)(NMPlatform *self, int ifindex, NMEthtoolPauseState *pause); gboolean (*ethtool_set_pause)(NMPlatform *self, int ifindex, const NMEthtoolPauseState *pause); + gboolean (*ethtool_get_eee)(NMPlatform *self, int ifindex, NMEthtoolEEEState *eee); + gboolean (*ethtool_set_eee)(NMPlatform *self, int ifindex, const NMEthtoolEEEState *eee); } NMPlatformClass; diff --git a/src/libnm-platform/nmp-ethtool-ioctl.c b/src/libnm-platform/nmp-ethtool-ioctl.c index c44d67c642..bbc9d5e760 100644 --- a/src/libnm-platform/nmp-ethtool-ioctl.c +++ b/src/libnm-platform/nmp-ethtool-ioctl.c @@ -1090,66 +1090,6 @@ nmp_ethtool_ioctl_set_channels(int ifindex, const NMEthtoolChannelsState *channe return TRUE; } -gboolean -nmp_ethtool_ioctl_get_eee(int ifindex, NMEthtoolEEEState *eee) -{ - struct ethtool_eee eth_data; - nm_auto_socket_handle SocketHandle shandle = SOCKET_HANDLE_INIT(ifindex); - - g_return_val_if_fail(ifindex > 0, FALSE); - g_return_val_if_fail(eee, FALSE); - - eth_data.cmd = ETHTOOL_GEEE; - if (_ethtool_call_handle(&shandle, ð_data, sizeof(struct ethtool_eee)) != 0) { - nm_log_trace(LOGD_PLATFORM, - "ethtool[%d]: %s: failure getting eee settings", - ifindex, - "get-eee"); - return FALSE; - } - - *eee = (NMEthtoolEEEState) { - .enabled = eth_data.eee_enabled == 1, - }; - - nm_log_trace(LOGD_PLATFORM, - "ethtool[%d]: %s: retrieved kernel eee settings", - ifindex, - "get-eee"); - return TRUE; -} - -gboolean -nmp_ethtool_ioctl_set_eee(int ifindex, const NMEthtoolEEEState *eee) -{ - struct ethtool_eee eth_data; - nm_auto_socket_handle SocketHandle shandle = SOCKET_HANDLE_INIT(ifindex); - - g_return_val_if_fail(ifindex > 0, FALSE); - g_return_val_if_fail(eee, FALSE); - - eth_data.cmd = ETHTOOL_GEEE; - if (_ethtool_call_handle(&shandle, ð_data, sizeof(struct ethtool_eee)) != 0) { - nm_log_trace(LOGD_PLATFORM, - "ethtool[%d]: %s: failure getting eee settings", - ifindex, - "get-eee"); - return FALSE; - } - - eth_data.cmd = ETHTOOL_SEEE, eth_data.eee_enabled = eee->enabled ? 1 : 0; - - if (_ethtool_call_handle(&shandle, ð_data, sizeof(struct ethtool_eee)) != 0) { - nm_log_trace(LOGD_PLATFORM, - "ethtool[%d]: %s: failure setting eee settings", - ifindex, - "set-eee"); - return FALSE; - } - nm_log_trace(LOGD_PLATFORM, "ethtool[%d]: %s: set kernel eee settings", ifindex, "set-eee"); - return TRUE; -} - gboolean nmp_ethtool_ioctl_get_fec_mode(int ifindex, uint32_t *fec_mode) { diff --git a/src/libnm-platform/nmp-ethtool-ioctl.h b/src/libnm-platform/nmp-ethtool-ioctl.h index 4d446c218f..97c2ff14e6 100644 --- a/src/libnm-platform/nmp-ethtool-ioctl.h +++ b/src/libnm-platform/nmp-ethtool-ioctl.h @@ -50,10 +50,6 @@ gboolean nmp_ethtool_ioctl_get_channels(int ifindex, NMEthtoolChannelsState *cha gboolean nmp_ethtool_ioctl_set_channels(int ifindex, const NMEthtoolChannelsState *channels); -gboolean nmp_ethtool_ioctl_get_eee(int ifindex, NMEthtoolEEEState *eee); - -gboolean nmp_ethtool_ioctl_set_eee(int ifindex, const NMEthtoolEEEState *eee); - gboolean nmp_ethtool_ioctl_get_fec_mode(int ifindex, uint32_t *fec_mode); gboolean nmp_ethtool_ioctl_set_fec_mode(int ifindex, uint32_t fec_mode); diff --git a/src/libnm-platform/nmp-ethtool.c b/src/libnm-platform/nmp-ethtool.c index 30cc1895e7..d502c4f946 100644 --- a/src/libnm-platform/nmp-ethtool.c +++ b/src/libnm-platform/nmp-ethtool.c @@ -317,3 +317,108 @@ nmp_ethtool_set_pause(struct nl_sock *genl_sock, nla_put_failure: g_return_val_if_reached(FALSE); } + +/*****************************************************************************/ +/* EEE */ +/*****************************************************************************/ + +enum { + ETHTOOL_A_EEE_UNSPEC, + ETHTOOL_A_EEE_HEADER, /* nest - _A_HEADER_* */ + ETHTOOL_A_EEE_MODES_OURS, /* bitset */ + ETHTOOL_A_EEE_MODES_PEER, /* bitset */ + ETHTOOL_A_EEE_ACTIVE, /* u8 */ + ETHTOOL_A_EEE_ENABLED, /* u8 */ + + /* add new constants above here */ + __ETHTOOL_A_EEE_CNT, + ETHTOOL_A_EEE_MAX = (__ETHTOOL_A_EEE_CNT - 1) +}; + +static int +ethtool_parse_eee(const struct nl_msg *msg, void *data) +{ + NMEthtoolEEEState *eee = data; + static const struct nla_policy policy[] = { + [ETHTOOL_A_EEE_ENABLED] = {.type = NLA_U8}, + }; + struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); + struct nlattr *tb[G_N_ELEMENTS(policy)]; + + *eee = (NMEthtoolEEEState) {}; + + if (nla_parse_arr(tb, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), policy) < 0) + return NL_SKIP; + + if (tb[ETHTOOL_A_EEE_ENABLED]) + eee->enabled = !!nla_get_u8(tb[ETHTOOL_A_EEE_ENABLED]); + + return NL_OK; +} + +gboolean +nmp_ethtool_get_eee(struct nl_sock *genl_sock, + guint16 family_id, + int ifindex, + NMEthtoolEEEState *eee) +{ + nm_auto_nlmsg struct nl_msg *msg = NULL; + gs_free char *err_msg = NULL; + int r; + + g_return_val_if_fail(eee, FALSE); + + _LOGT("get-eee: start"); + *eee = (NMEthtoolEEEState) {}; + + msg = ethtool_create_msg(family_id, + ifindex, + ETHTOOL_MSG_EEE_GET, + ETHTOOL_A_EEE_HEADER, + "get-eee"); + if (!msg) + return FALSE; + + r = ethtool_send_and_recv(genl_sock, ifindex, msg, ethtool_parse_eee, eee, &err_msg, "get-eee"); + if (r < 0) + return FALSE; + + _LOGT("get-eee: enabled %d", eee->enabled); + + return TRUE; +} + +gboolean +nmp_ethtool_set_eee(struct nl_sock *genl_sock, + guint16 family_id, + int ifindex, + const NMEthtoolEEEState *eee) +{ + nm_auto_nlmsg struct nl_msg *msg = NULL; + gs_free char *err_msg = NULL; + int r; + + g_return_val_if_fail(eee, FALSE); + + _LOGT("set-eee: enabled %d", eee->enabled); + + msg = ethtool_create_msg(family_id, + ifindex, + ETHTOOL_MSG_EEE_SET, + ETHTOOL_A_EEE_HEADER, + "set-eee"); + if (!msg) + return FALSE; + + NLA_PUT_U8(msg, ETHTOOL_A_EEE_ENABLED, eee->enabled); + + r = ethtool_send_and_recv(genl_sock, ifindex, msg, NULL, NULL, &err_msg, "set-eee"); + if (r < 0) + return FALSE; + + _LOGT("set-eee: succeeded"); + + return TRUE; +nla_put_failure: + g_return_val_if_reached(FALSE); +} diff --git a/src/libnm-platform/nmp-ethtool.h b/src/libnm-platform/nmp-ethtool.h index 36b4e0b075..73e4b34826 100644 --- a/src/libnm-platform/nmp-ethtool.h +++ b/src/libnm-platform/nmp-ethtool.h @@ -14,4 +14,13 @@ gboolean nmp_ethtool_set_pause(struct nl_sock *genl_sock, int ifindex, const NMEthtoolPauseState *pause); +gboolean nmp_ethtool_get_eee(struct nl_sock *genl_sock, + guint16 family_id, + int ifindex, + NMEthtoolEEEState *eee); +gboolean nmp_ethtool_set_eee(struct nl_sock *genl_sock, + guint16 family_id, + int ifindex, + const NMEthtoolEEEState *eee); + #endif /* __NMP_ETHTOOL_H__ */