diff --git a/src/libnm-platform/nm-linux-platform.c b/src/libnm-platform/nm-linux-platform.c index 5fe0ff036..ff994ff5d 100644 --- a/src/libnm-platform/nm-linux-platform.c +++ b/src/libnm-platform/nm-linux-platform.c @@ -11877,6 +11877,28 @@ ethtool_set_eee(NMPlatform *platform, int ifindex, const NMEthtoolEEEState *eee) eee); } +static gboolean +ethtool_get_ring(NMPlatform *platform, int ifindex, NMEthtoolRingState *ring) +{ + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); + + return nmp_ethtool_get_ring(priv->sk_genl_sync, + genl_get_family_id(platform, NMP_GENL_FAMILY_TYPE_ETHTOOL), + ifindex, + ring); +} + +static gboolean +ethtool_set_ring(NMPlatform *platform, int ifindex, const NMEthtoolRingState *ring) +{ + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform); + + return nmp_ethtool_set_ring(priv->sk_genl_sync, + genl_get_family_id(platform, NMP_GENL_FAMILY_TYPE_ETHTOOL), + ifindex, + ring); +} + /*****************************************************************************/ static void @@ -12381,4 +12403,6 @@ nm_linux_platform_class_init(NMLinuxPlatformClass *klass) platform_class->ethtool_get_pause = ethtool_get_pause; platform_class->ethtool_set_eee = ethtool_set_eee; platform_class->ethtool_get_eee = ethtool_get_eee; + platform_class->ethtool_set_ring = ethtool_set_ring; + platform_class->ethtool_get_ring = ethtool_get_ring; } diff --git a/src/libnm-platform/nm-platform.c b/src/libnm-platform/nm-platform.c index 47db1c40b..fd966d2ce 100644 --- a/src/libnm-platform/nm-platform.c +++ b/src/libnm-platform/nm-platform.c @@ -3671,7 +3671,7 @@ nm_platform_ethtool_get_ring(NMPlatform *self, int ifindex, NMEthtoolRingState * g_return_val_if_fail(ifindex > 0, FALSE); g_return_val_if_fail(ring, FALSE); - return nmp_ethtool_ioctl_get_ring(ifindex, ring); + return klass->ethtool_get_ring(self, ifindex, ring); } gboolean @@ -3680,8 +3680,9 @@ nm_platform_ethtool_set_ring(NMPlatform *self, int ifindex, const NMEthtoolRingS _CHECK_SELF_NETNS(self, klass, netns, FALSE); g_return_val_if_fail(ifindex > 0, FALSE); + g_return_val_if_fail(ring, FALSE); - return nmp_ethtool_ioctl_set_ring(ifindex, ring); + return klass->ethtool_set_ring(self, ifindex, ring); } gboolean diff --git a/src/libnm-platform/nm-platform.h b/src/libnm-platform/nm-platform.h index 405a2d012..e4ccb9b1c 100644 --- a/src/libnm-platform/nm-platform.h +++ b/src/libnm-platform/nm-platform.h @@ -1350,7 +1350,8 @@ typedef struct { 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); - + gboolean (*ethtool_get_ring)(NMPlatform *self, int ifindex, NMEthtoolRingState *ring); + gboolean (*ethtool_set_ring)(NMPlatform *self, int ifindex, const NMEthtoolRingState *ring); } NMPlatformClass; /* NMPlatform signals diff --git a/src/libnm-platform/nmp-ethtool-ioctl.c b/src/libnm-platform/nmp-ethtool-ioctl.c index bbc9d5e76..830b02f6c 100644 --- a/src/libnm-platform/nmp-ethtool-ioctl.c +++ b/src/libnm-platform/nmp-ethtool-ioctl.c @@ -967,66 +967,6 @@ nmp_ethtool_ioctl_set_coalesce(int ifindex, const NMEthtoolCoalesceState *coales return TRUE; } -gboolean -nmp_ethtool_ioctl_get_ring(int ifindex, NMEthtoolRingState *ring) -{ - struct ethtool_ringparam eth_data; - - g_return_val_if_fail(ifindex > 0, FALSE); - g_return_val_if_fail(ring, FALSE); - - eth_data.cmd = ETHTOOL_GRINGPARAM; - - if (_ethtool_call_once(ifindex, ð_data, sizeof(eth_data)) < 0) { - nm_log_trace(LOGD_PLATFORM, - "ethtool[%d]: %s: failure getting ring settings", - ifindex, - "get-ring"); - return FALSE; - } - - *ring = (NMEthtoolRingState) { - .rx_pending = eth_data.rx_pending, - .rx_jumbo_pending = eth_data.rx_jumbo_pending, - .rx_mini_pending = eth_data.rx_mini_pending, - .tx_pending = eth_data.tx_pending, - }; - - nm_log_trace(LOGD_PLATFORM, - "ethtool[%d]: %s: retrieved kernel ring settings", - ifindex, - "get-ring"); - return TRUE; -} - -gboolean -nmp_ethtool_ioctl_set_ring(int ifindex, const NMEthtoolRingState *ring) -{ - struct ethtool_ringparam eth_data; - - g_return_val_if_fail(ifindex > 0, FALSE); - g_return_val_if_fail(ring, FALSE); - - eth_data = (struct ethtool_ringparam) { - .cmd = ETHTOOL_SRINGPARAM, - .rx_pending = ring->rx_pending, - .rx_jumbo_pending = ring->rx_jumbo_pending, - .rx_mini_pending = ring->rx_mini_pending, - .tx_pending = ring->tx_pending, - }; - - if (_ethtool_call_once(ifindex, ð_data, sizeof(eth_data)) < 0) { - nm_log_trace(LOGD_PLATFORM, - "ethtool[%d]: %s: failure setting ring settings", - ifindex, - "set-ring"); - return FALSE; - } - - nm_log_trace(LOGD_PLATFORM, "ethtool[%d]: %s: set kernel ring settings", ifindex, "set-ring"); - return TRUE; -} - gboolean nmp_ethtool_ioctl_get_channels(int ifindex, NMEthtoolChannelsState *channels) { diff --git a/src/libnm-platform/nmp-ethtool-ioctl.h b/src/libnm-platform/nmp-ethtool-ioctl.h index 97c2ff14e..cb93e9cf5 100644 --- a/src/libnm-platform/nmp-ethtool-ioctl.h +++ b/src/libnm-platform/nmp-ethtool-ioctl.h @@ -42,10 +42,6 @@ gboolean nmp_ethtool_ioctl_get_coalesce(int ifindex, NMEthtoolCoalesceState *coa gboolean nmp_ethtool_ioctl_set_coalesce(int ifindex, const NMEthtoolCoalesceState *coalesce); -gboolean nmp_ethtool_ioctl_get_ring(int ifindex, NMEthtoolRingState *ring); - -gboolean nmp_ethtool_ioctl_set_ring(int ifindex, const NMEthtoolRingState *ring); - gboolean nmp_ethtool_ioctl_get_channels(int ifindex, NMEthtoolChannelsState *channels); gboolean nmp_ethtool_ioctl_set_channels(int ifindex, const NMEthtoolChannelsState *channels); diff --git a/src/libnm-platform/nmp-ethtool.c b/src/libnm-platform/nmp-ethtool.c index d502c4f94..ed028f6a1 100644 --- a/src/libnm-platform/nmp-ethtool.c +++ b/src/libnm-platform/nmp-ethtool.c @@ -422,3 +422,138 @@ nmp_ethtool_set_eee(struct nl_sock *genl_sock, nla_put_failure: g_return_val_if_reached(FALSE); } + +/*****************************************************************************/ +/* RINGS */ +/*****************************************************************************/ + +enum { + ETHTOOL_A_RINGS_UNSPEC, + ETHTOOL_A_RINGS_HEADER, /* nest - _A_HEADER_* */ + ETHTOOL_A_RINGS_RX_MAX, /* u32 */ + ETHTOOL_A_RINGS_RX_MINI_MAX, /* u32 */ + ETHTOOL_A_RINGS_RX_JUMBO_MAX, /* u32 */ + ETHTOOL_A_RINGS_TX_MAX, /* u32 */ + ETHTOOL_A_RINGS_RX, /* u32 */ + ETHTOOL_A_RINGS_RX_MINI, /* u32 */ + ETHTOOL_A_RINGS_RX_JUMBO, /* u32 */ + ETHTOOL_A_RINGS_TX, /* u32 */ + + /* add new constants above here */ + __ETHTOOL_A_RINGS_CNT, + ETHTOOL_A_RINGS_MAX = (__ETHTOOL_A_RINGS_CNT - 1) +}; + +static int +ethtool_parse_ring(const struct nl_msg *msg, void *data) +{ + NMEthtoolRingState *ring = data; + static const struct nla_policy policy[] = { + [ETHTOOL_A_RINGS_RX] = {.type = NLA_U32}, + [ETHTOOL_A_RINGS_RX_MINI] = {.type = NLA_U32}, + [ETHTOOL_A_RINGS_RX_JUMBO] = {.type = NLA_U32}, + [ETHTOOL_A_RINGS_TX] = {.type = NLA_U32}, + }; + struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); + struct nlattr *tb[G_N_ELEMENTS(policy)]; + + *ring = (NMEthtoolRingState) {}; + + if (nla_parse_arr(tb, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), policy) < 0) + return NL_SKIP; + + if (tb[ETHTOOL_A_RINGS_RX]) + ring->rx_pending = nla_get_u32(tb[ETHTOOL_A_RINGS_RX]); + if (tb[ETHTOOL_A_RINGS_RX_MINI]) + ring->rx_mini_pending = nla_get_u32(tb[ETHTOOL_A_RINGS_RX_MINI]); + if (tb[ETHTOOL_A_RINGS_RX_JUMBO]) + ring->rx_jumbo_pending = nla_get_u32(tb[ETHTOOL_A_RINGS_RX_JUMBO]); + if (tb[ETHTOOL_A_RINGS_TX]) + ring->tx_pending = nla_get_u32(tb[ETHTOOL_A_RINGS_TX]); + + return NL_OK; +} + +gboolean +nmp_ethtool_get_ring(struct nl_sock *genl_sock, + guint16 family_id, + int ifindex, + NMEthtoolRingState *ring) +{ + nm_auto_nlmsg struct nl_msg *msg = NULL; + gs_free char *err_msg = NULL; + int r; + + g_return_val_if_fail(ring, FALSE); + + _LOGT("get-ring: start"); + *ring = (NMEthtoolRingState) {}; + + msg = ethtool_create_msg(family_id, + ifindex, + ETHTOOL_MSG_RINGS_GET, + ETHTOOL_A_RINGS_HEADER, + "get-ring"); + if (!msg) + return FALSE; + + r = ethtool_send_and_recv(genl_sock, + ifindex, + msg, + ethtool_parse_ring, + ring, + &err_msg, + "get-ring"); + if (r < 0) + return FALSE; + + _LOGT("get-ring: rx %u rx-mini %u rx-jumbo %u tx %u", + ring->rx_pending, + ring->rx_mini_pending, + ring->rx_jumbo_pending, + ring->tx_pending); + + return TRUE; +} + +gboolean +nmp_ethtool_set_ring(struct nl_sock *genl_sock, + guint16 family_id, + int ifindex, + const NMEthtoolRingState *ring) +{ + nm_auto_nlmsg struct nl_msg *msg = NULL; + gs_free char *err_msg = NULL; + int r; + + g_return_val_if_fail(ring, FALSE); + + _LOGT("set-ring: rx %u rx-mini %u rx-jumbo %u tx %u", + ring->rx_pending, + ring->rx_mini_pending, + ring->rx_jumbo_pending, + ring->tx_pending); + + msg = ethtool_create_msg(family_id, + ifindex, + ETHTOOL_MSG_RINGS_SET, + ETHTOOL_A_RINGS_HEADER, + "set-ring"); + if (!msg) + return FALSE; + + NLA_PUT_U32(msg, ETHTOOL_A_RINGS_RX, ring->rx_pending); + NLA_PUT_U32(msg, ETHTOOL_A_RINGS_RX_MINI, ring->rx_mini_pending); + NLA_PUT_U32(msg, ETHTOOL_A_RINGS_RX_JUMBO, ring->rx_jumbo_pending); + NLA_PUT_U32(msg, ETHTOOL_A_RINGS_TX, ring->tx_pending); + + r = ethtool_send_and_recv(genl_sock, ifindex, msg, NULL, NULL, &err_msg, "set-ring"); + if (r < 0) + return FALSE; + + _LOGT("set-ring: 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 73e4b3482..88bb95b68 100644 --- a/src/libnm-platform/nmp-ethtool.h +++ b/src/libnm-platform/nmp-ethtool.h @@ -23,4 +23,13 @@ gboolean nmp_ethtool_set_eee(struct nl_sock *genl_sock, int ifindex, const NMEthtoolEEEState *eee); +gboolean nmp_ethtool_get_ring(struct nl_sock *genl_sock, + guint16 family_id, + int ifindex, + NMEthtoolRingState *ring); +gboolean nmp_ethtool_set_ring(struct nl_sock *genl_sock, + guint16 family_id, + int ifindex, + const NMEthtoolRingState *ring); + #endif /* __NMP_ETHTOOL_H__ */