merge: branch 'bg/ethtool-netlink'

https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/2169
This commit is contained in:
Beniamino Galvani 2025-04-17 08:11:54 +02:00
commit 7b2924b762
16 changed files with 2419 additions and 1895 deletions

View file

@ -112,6 +112,14 @@ contrib/fedora/rpm/NetworkManager.conf for how to enable debug logging
in NetworkManager.
Requirements
------------
NetworkManager requires:
- Linux kernel >= 5.6 for some ethtool options (pause, eee, ring)
Documentation
-------------

View file

@ -2746,7 +2746,7 @@ _ethtool_features_set(NMDevice *self,
if (nm_setting_ethtool_init_features(s_ethtool, ethtool_state->requested) == 0)
return;
features = nm_platform_ethtool_get_link_features(platform, ethtool_state->ifindex);
features = nm_platform_ethtool_get_features(platform, ethtool_state->ifindex);
if (!features) {
_LOGW(LOGD_DEVICE, "ethtool: failure setting offload features (cannot read features)");
return;
@ -2865,9 +2865,9 @@ _ethtool_coalesce_set(NMDevice *self,
continue;
if (!has_old) {
if (!nm_platform_ethtool_get_link_coalesce(platform,
ethtool_state->ifindex,
&coalesce_old)) {
if (!nm_platform_ethtool_get_coalesce(platform,
ethtool_state->ifindex,
&coalesce_old)) {
_LOGW(LOGD_DEVICE, "ethtool: failure getting coalesce settings (cannot read)");
return;
}
@ -2946,7 +2946,7 @@ _ethtool_ring_set(NMDevice *self,
nm_assert(g_variant_is_of_type(variant, G_VARIANT_TYPE_UINT32));
if (!has_old) {
if (!nm_platform_ethtool_get_link_ring(platform, ethtool_state->ifindex, &ring_old)) {
if (!nm_platform_ethtool_get_ring(platform, ethtool_state->ifindex, &ring_old)) {
_LOGW(LOGD_DEVICE,
"ethtool: failure setting ring options (cannot read existing setting)");
return;
@ -3042,9 +3042,9 @@ _ethtool_channels_set(NMDevice *self,
nm_assert(g_variant_is_of_type(variant, G_VARIANT_TYPE_UINT32));
if (!has_old) {
if (!nm_platform_ethtool_get_link_channels(platform,
ethtool_state->ifindex,
&channels_old)) {
if (!nm_platform_ethtool_get_channels(platform,
ethtool_state->ifindex,
&channels_old)) {
_LOGW(LOGD_DEVICE,
"ethtool: failure setting channels options (cannot read existing setting)");
return;
@ -3161,7 +3161,7 @@ _ethtool_pause_set(NMDevice *self,
nm_assert(g_variant_is_of_type(variant, G_VARIANT_TYPE_BOOLEAN));
if (!has_old) {
if (!nm_platform_ethtool_get_link_pause(platform, ethtool_state->ifindex, &pause_old)) {
if (!nm_platform_ethtool_get_pause(platform, ethtool_state->ifindex, &pause_old)) {
_LOGW(LOGD_DEVICE,
"ethtool: failure setting pause options (cannot read "
"existing setting)");
@ -3247,7 +3247,7 @@ _ethtool_eee_set(NMDevice *self,
nm_assert(g_variant_is_of_type(variant, G_VARIANT_TYPE_BOOLEAN));
if (!has_old) {
if (!nm_platform_ethtool_get_link_eee(platform, ethtool_state->ifindex, &eee_old)) {
if (!nm_platform_ethtool_get_eee(platform, ethtool_state->ifindex, &eee_old)) {
_LOGW(LOGD_DEVICE,
"ethtool: failure setting eee options (cannot read "
"existing setting)");

View file

@ -15,6 +15,7 @@
#include "libnm-base/nm-ethtool-base.h"
#include "libnm-platform/nmp-object.h"
#include "libnm-platform/nmp-netns.h"
#include "libnm-platform/nmp-ethtool-ioctl.h"
#include "libnm-platform/nm-platform-utils.h"
#include "test-common.h"
@ -3183,10 +3184,10 @@ test_netns_general(gpointer fixture, gconstpointer test_data)
* Work around that and skip asserts that are known to fail. */
ethtool_support = nmtstp_run_command("ethtool -i dummy1_ > /dev/null") == 0;
if (ethtool_support) {
g_assert(nmp_utils_ethtool_get_driver_info(
g_assert(nmp_ethtool_ioctl_get_driver_info(
nmtstp_link_get_typed(platform_1, 0, "dummy1_", NM_LINK_TYPE_DUMMY)->ifindex,
&driver_info));
g_assert(nmp_utils_ethtool_get_driver_info(
g_assert(nmp_ethtool_ioctl_get_driver_info(
nmtstp_link_get_typed(platform_1, 0, "dummy2a", NM_LINK_TYPE_DUMMY)->ifindex,
&driver_info));
g_assert_cmpint(nmtstp_run_command("ethtool -i dummy1_ > /dev/null"), ==, 0);
@ -3197,10 +3198,10 @@ test_netns_general(gpointer fixture, gconstpointer test_data)
g_assert(nm_platform_netns_push(platform_2, &netns_tmp));
if (ethtool_support) {
g_assert(nmp_utils_ethtool_get_driver_info(
g_assert(nmp_ethtool_ioctl_get_driver_info(
nmtstp_link_get_typed(platform_2, 0, "dummy1_", NM_LINK_TYPE_DUMMY)->ifindex,
&driver_info));
g_assert(nmp_utils_ethtool_get_driver_info(
g_assert(nmp_ethtool_ioctl_get_driver_info(
nmtstp_link_get_typed(platform_2, 0, "dummy2b", NM_LINK_TYPE_DUMMY)->ifindex,
&driver_info));
g_assert_cmpint(nmtstp_run_command("ethtool -i dummy1_ > /dev/null"), ==, 0);
@ -4031,7 +4032,7 @@ test_ethtool_features_get(void)
_LOGT(">>> ethtool-features-get RUN %u (do-set=%s", i_run, do_set ? "set" : "reset");
features = nmp_utils_ethtool_get_features(IFINDEX);
features = nmp_ethtool_ioctl_get_features(IFINDEX);
g_ptr_array_add(gfree_keeper, features);
ethtool_features_dump(features);
@ -4044,7 +4045,7 @@ test_ethtool_features_get(void)
features = gfree_keeper->pdata[i_run * 2 - 1];
}
nmp_utils_ethtool_set_features(IFINDEX, features, requested, do_set);
nmp_ethtool_ioctl_set_features(IFINDEX, features, requested, do_set);
}
}

View file

@ -14,6 +14,7 @@
#include "libnm-platform/nm-netlink.h"
#include "libnm-platform/nm-platform.h"
#include "libnm-platform/nm-platform-utils.h"
#include "libnm-platform/nmp-ethtool-ioctl.h"
#define _NMLOG_PREFIX_NAME "devlink"
#define _NMLOG_DOMAIN LOGD_PLATFORM | LOGD_DEVICE
@ -118,7 +119,7 @@ nm_devlink_get_dev_identifier(NMDevlink *self, char **out_bus, char **out_addr,
return FALSE;
}
if (!nmp_utils_ethtool_get_driver_info(self->ifindex, &ethtool_driver_info)) {
if (!nmp_ethtool_ioctl_get_driver_info(self->ifindex, &ethtool_driver_info)) {
g_set_error(error,
NM_UTILS_ERROR,
NM_UTILS_ERROR_UNKNOWN,

View file

@ -12,6 +12,8 @@ libnm_platform = static_library(
'nmp-netns.c',
'nmp-object.c',
'nmp-plobj.c',
'nmp-ethtool.c',
'nmp-ethtool-ioctl.c',
'devlink/nm-devlink.c',
'wifi/nm-wifi-utils-nl80211.c',
'wifi/nm-wifi-utils.c',

View file

@ -41,6 +41,8 @@
#include "libnm-platform/nm-netlink.h"
#include "libnm-platform/nm-platform-utils.h"
#include "libnm-platform/nmp-netns.h"
#include "libnm-platform/nmp-ethtool.h"
#include "libnm-platform/nmp-ethtool-ioctl.h"
#include "libnm-platform/devlink/nm-devlink.h"
#include "libnm-platform/wifi/nm-wifi-utils-wext.h"
#include "libnm-platform/wifi/nm-wifi-utils.h"
@ -1320,7 +1322,7 @@ _linktype_get_type(NMPlatform *platform,
NMPUtilsEthtoolDriverInfo driver_info;
/* Fallback OVS detection for kernel <= 3.16 */
if (nmp_utils_ethtool_get_driver_info(ifindex, &driver_info)) {
if (nmp_ethtool_ioctl_get_driver_info(ifindex, &driver_info)) {
if (nm_streq(driver_info.driver, "openvswitch"))
return NM_LINK_TYPE_OPENVSWITCH;
@ -8966,8 +8968,8 @@ link_supports_carrier_detect(NMPlatform *platform, int ifindex)
* us whether the device actually supports carrier detection in the first
* place. We assume any device that does implements one of these two APIs.
*/
return nmp_utils_ethtool_supports_carrier_detect(ifindex)
|| nmp_utils_mii_supports_carrier_detect(ifindex);
return nmp_ethtool_ioctl_supports_carrier_detect(ifindex)
|| nmp_mii_ioctl_supports_carrier_detect(ifindex);
}
static gboolean
@ -8985,7 +8987,7 @@ link_supports_vlans(NMPlatform *platform, int ifindex)
if (!nm_platform_netns_push(platform, &netns))
return FALSE;
return nmp_utils_ethtool_supports_vlans(ifindex);
return nmp_ethtool_ioctl_supports_vlans(ifindex);
}
static gboolean
@ -9063,7 +9065,7 @@ link_get_permanent_address_ethtool(NMPlatform *platform, int ifindex, NMPLinkAdd
if (!nm_platform_netns_push(platform, &netns))
return FALSE;
if (!nmp_utils_ethtool_get_permanent_address(ifindex, buffer, &len))
if (!nmp_ethtool_ioctl_get_permanent_address(ifindex, buffer, &len))
return FALSE;
nm_assert(len <= _NM_UTILS_HWADDR_LEN_MAX);
memcpy(out_address->data, buffer, len);
@ -10391,7 +10393,7 @@ link_get_wake_on_lan(NMPlatform *platform, int ifindex)
return FALSE;
if (type == NM_LINK_TYPE_ETHERNET)
return nmp_utils_ethtool_get_wake_on_lan(ifindex);
return nmp_ethtool_ioctl_get_wake_on_lan(ifindex);
else if (type == NM_LINK_TYPE_WIFI) {
WIFI_GET_WIFI_DATA(wifi_data, platform, ifindex, FALSE);
@ -10416,7 +10418,7 @@ link_get_driver_info(NMPlatform *platform,
if (!nm_platform_netns_push(platform, &netns))
return FALSE;
if (!nmp_utils_ethtool_get_driver_info(ifindex, &driver_info))
if (!nmp_ethtool_ioctl_get_driver_info(ifindex, &driver_info))
return FALSE;
NM_SET_OUT(out_driver_name, g_strdup(driver_info.driver));
NM_SET_OUT(out_driver_version, g_strdup(driver_info.version));
@ -11831,6 +11833,74 @@ mptcp_addrs_dump(NMPlatform *platform)
/*****************************************************************************/
static gboolean
ethtool_get_pause(NMPlatform *platform, int ifindex, NMEthtoolPauseState *pause)
{
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform);
return nmp_ethtool_get_pause(priv->sk_genl_sync,
genl_get_family_id(platform, NMP_GENL_FAMILY_TYPE_ETHTOOL),
ifindex,
pause);
}
static gboolean
ethtool_set_pause(NMPlatform *platform, int ifindex, const NMEthtoolPauseState *pause)
{
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE(platform);
return nmp_ethtool_set_pause(priv->sk_genl_sync,
genl_get_family_id(platform, NMP_GENL_FAMILY_TYPE_ETHTOOL),
ifindex,
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 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
cache_update_link_udev(NMPlatform *platform, int ifindex, struct udev_device *udevice)
{
@ -12328,4 +12398,11 @@ nm_linux_platform_class_init(NMLinuxPlatformClass *klass)
platform_class->genl_get_family_id = genl_get_family_id;
platform_class->mptcp_addr_update = mptcp_addr_update;
platform_class->mptcp_addrs_dump = mptcp_addrs_dump;
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;
platform_class->ethtool_set_ring = ethtool_set_ring;
platform_class->ethtool_get_ring = ethtool_get_ring;
}

File diff suppressed because it is too large Load diff

View file

@ -8,72 +8,17 @@
#include "libnm-base/nm-base.h"
#include "libnm-platform/nmp-base.h"
#include "libnm-platform/nm-platform.h"
/*****************************************************************************/
const char *nmp_utils_ethtool_get_driver(int ifindex);
gboolean nmp_utils_ethtool_supports_carrier_detect(int ifindex);
gboolean nmp_utils_ethtool_supports_vlans(int ifindex);
int nmp_utils_ethtool_get_peer_ifindex(int ifindex);
gboolean nmp_utils_ethtool_get_wake_on_lan(int ifindex);
gboolean nmp_utils_ethtool_set_wake_on_lan(int ifindex,
_NMSettingWiredWakeOnLan wol,
const char *wol_password);
const char *nm_platform_link_duplex_type_to_string(NMPlatformLinkDuplexType duplex);
extern const guint8 _nmp_link_mode_all_advertised_modes_bits[79];
extern const guint32 _nmp_link_mode_all_advertised_modes[3];
gboolean nmp_utils_ethtool_get_link_settings(int ifindex,
gboolean *out_autoneg,
guint32 *out_speed,
NMPlatformLinkDuplexType *out_duplex);
gboolean nmp_utils_ethtool_set_link_settings(int ifindex,
gboolean autoneg,
guint32 speed,
NMPlatformLinkDuplexType duplex);
gboolean nmp_utils_ethtool_get_permanent_address(int ifindex, guint8 *buf, size_t *length);
gboolean nmp_utils_ethtool_get_driver_info(int ifindex, NMPUtilsEthtoolDriverInfo *data);
NMEthtoolFeatureStates *nmp_utils_ethtool_get_features(int ifindex);
gboolean nmp_utils_ethtool_set_features(
int ifindex,
const NMEthtoolFeatureStates *features,
const NMOptionBool *requested /* indexed by NMEthtoolID - _NM_ETHTOOL_ID_FEATURE_FIRST */,
gboolean do_set /* or reset */);
gboolean nmp_utils_ethtool_get_coalesce(int ifindex, NMEthtoolCoalesceState *coalesce);
gboolean nmp_utils_ethtool_set_coalesce(int ifindex, const NMEthtoolCoalesceState *coalesce);
gboolean nmp_utils_ethtool_get_ring(int ifindex, NMEthtoolRingState *ring);
gboolean nmp_utils_ethtool_set_ring(int ifindex, const NMEthtoolRingState *ring);
gboolean nmp_utils_ethtool_get_channels(int ifindex, NMEthtoolChannelsState *channels);
gboolean nmp_utils_ethtool_set_channels(int ifindex, const NMEthtoolChannelsState *channels);
gboolean nmp_utils_ethtool_get_pause(int ifindex, NMEthtoolPauseState *pause);
gboolean nmp_utils_ethtool_set_pause(int ifindex, const NMEthtoolPauseState *pause);
gboolean nmp_utils_ethtool_get_eee(int ifindex, NMEthtoolEEEState *eee);
gboolean nmp_utils_ethtool_set_eee(int ifindex, const NMEthtoolEEEState *eee);
gboolean nmp_utils_ethtool_get_fec_mode(int ifindex, uint32_t *fec_mode);
gboolean nmp_utils_ethtool_set_fec_mode(int ifindex, uint32_t fec_mode);
/*****************************************************************************/
gboolean nmp_utils_mii_supports_carrier_detect(int ifindex);
struct udev_device;
const char *nmp_utils_udev_get_driver(struct udev_device *udevice);

View file

@ -31,6 +31,7 @@
#include "libnm-log-core/nm-logging.h"
#include "libnm-platform/nm-platform-utils.h"
#include "libnm-platform/nmp-netns.h"
#include "libnm-platform/nmp-ethtool-ioctl.h"
#include "libnm-udev-aux/nm-udev-utils.h"
#include "nm-platform-private.h"
#include "nmp-object.h"
@ -3230,7 +3231,7 @@ nm_platform_link_veth_get_properties(NMPlatform *self, int ifindex, int *out_pee
if (!nm_platform_netns_push(self, &netns))
return FALSE;
peer_ifindex = nmp_utils_ethtool_get_peer_ifindex(plink->ifindex);
peer_ifindex = nmp_ethtool_ioctl_get_peer_ifindex(plink->ifindex);
if (peer_ifindex <= 0)
return FALSE;
@ -3561,7 +3562,7 @@ nm_platform_ethtool_set_wake_on_lan(NMPlatform *self,
g_return_val_if_fail(ifindex > 0, FALSE);
return nmp_utils_ethtool_set_wake_on_lan(ifindex, wol, wol_password);
return nmp_ethtool_ioctl_set_wake_on_lan(ifindex, wol, wol_password);
}
gboolean
@ -3575,7 +3576,7 @@ nm_platform_ethtool_set_link_settings(NMPlatform *self,
g_return_val_if_fail(ifindex > 0, FALSE);
return nmp_utils_ethtool_set_link_settings(ifindex, autoneg, speed, duplex);
return nmp_ethtool_ioctl_set_link_settings(ifindex, autoneg, speed, duplex);
}
gboolean
@ -3589,19 +3590,19 @@ nm_platform_ethtool_get_link_settings(NMPlatform *self,
g_return_val_if_fail(ifindex > 0, FALSE);
return nmp_utils_ethtool_get_link_settings(ifindex, out_autoneg, out_speed, out_duplex);
return nmp_ethtool_ioctl_get_link_settings(ifindex, out_autoneg, out_speed, out_duplex);
}
/*****************************************************************************/
NMEthtoolFeatureStates *
nm_platform_ethtool_get_link_features(NMPlatform *self, int ifindex)
nm_platform_ethtool_get_features(NMPlatform *self, int ifindex)
{
_CHECK_SELF_NETNS(self, klass, netns, NULL);
g_return_val_if_fail(ifindex > 0, NULL);
return nmp_utils_ethtool_get_features(ifindex);
return nmp_ethtool_ioctl_get_features(ifindex);
}
gboolean
@ -3616,7 +3617,7 @@ nm_platform_ethtool_set_features(
g_return_val_if_fail(ifindex > 0, FALSE);
return nmp_utils_ethtool_set_features(ifindex, features, requested, do_set);
return nmp_ethtool_ioctl_set_features(ifindex, features, requested, do_set);
}
gboolean
@ -3626,7 +3627,7 @@ nm_platform_ethtool_get_fec_mode(NMPlatform *self, int ifindex, uint32_t *fec_mo
g_return_val_if_fail(ifindex > 0, FALSE);
return nmp_utils_ethtool_get_fec_mode(ifindex, fec_mode);
return nmp_ethtool_ioctl_get_fec_mode(ifindex, fec_mode);
}
gboolean
@ -3636,20 +3637,18 @@ nm_platform_ethtool_set_fec_mode(NMPlatform *self, int ifindex, uint32_t fec_mod
g_return_val_if_fail(ifindex > 0, FALSE);
return nmp_utils_ethtool_set_fec_mode(ifindex, fec_mode);
return nmp_ethtool_ioctl_set_fec_mode(ifindex, fec_mode);
}
gboolean
nm_platform_ethtool_get_link_coalesce(NMPlatform *self,
int ifindex,
NMEthtoolCoalesceState *coalesce)
nm_platform_ethtool_get_coalesce(NMPlatform *self, int ifindex, NMEthtoolCoalesceState *coalesce)
{
_CHECK_SELF_NETNS(self, klass, netns, FALSE);
g_return_val_if_fail(ifindex > 0, FALSE);
g_return_val_if_fail(coalesce, FALSE);
return nmp_utils_ethtool_get_coalesce(ifindex, coalesce);
return nmp_ethtool_ioctl_get_coalesce(ifindex, coalesce);
}
gboolean
@ -3661,18 +3660,18 @@ nm_platform_ethtool_set_coalesce(NMPlatform *self,
g_return_val_if_fail(ifindex > 0, FALSE);
return nmp_utils_ethtool_set_coalesce(ifindex, coalesce);
return nmp_ethtool_ioctl_set_coalesce(ifindex, coalesce);
}
gboolean
nm_platform_ethtool_get_link_ring(NMPlatform *self, int ifindex, NMEthtoolRingState *ring)
nm_platform_ethtool_get_ring(NMPlatform *self, int ifindex, NMEthtoolRingState *ring)
{
_CHECK_SELF_NETNS(self, klass, netns, FALSE);
g_return_val_if_fail(ifindex > 0, FALSE);
g_return_val_if_fail(ring, FALSE);
return nmp_utils_ethtool_get_ring(ifindex, ring);
return klass->ethtool_get_ring(self, ifindex, ring);
}
gboolean
@ -3681,21 +3680,20 @@ 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_utils_ethtool_set_ring(ifindex, ring);
return klass->ethtool_set_ring(self, ifindex, ring);
}
gboolean
nm_platform_ethtool_get_link_channels(NMPlatform *self,
int ifindex,
NMEthtoolChannelsState *channels)
nm_platform_ethtool_get_channels(NMPlatform *self, int ifindex, NMEthtoolChannelsState *channels)
{
_CHECK_SELF_NETNS(self, klass, netns, FALSE);
g_return_val_if_fail(ifindex > 0, FALSE);
g_return_val_if_fail(channels, FALSE);
return nmp_utils_ethtool_get_channels(ifindex, channels);
return nmp_ethtool_ioctl_get_channels(ifindex, channels);
}
gboolean
@ -3707,29 +3705,18 @@ nm_platform_ethtool_set_channels(NMPlatform *self,
g_return_val_if_fail(ifindex > 0, FALSE);
return nmp_utils_ethtool_set_channels(ifindex, channels);
return nmp_ethtool_ioctl_set_channels(ifindex, channels);
}
gboolean
nm_platform_ethtool_get_link_pause(NMPlatform *self, int ifindex, NMEthtoolPauseState *pause)
nm_platform_ethtool_get_pause(NMPlatform *self, int ifindex, NMEthtoolPauseState *pause)
{
_CHECK_SELF_NETNS(self, klass, netns, FALSE);
g_return_val_if_fail(ifindex > 0, FALSE);
g_return_val_if_fail(pause, FALSE);
return nmp_utils_ethtool_get_pause(ifindex, pause);
}
gboolean
nm_platform_ethtool_get_link_eee(NMPlatform *self, int ifindex, NMEthtoolEEEState *eee)
{
_CHECK_SELF_NETNS(self, klass, netns, FALSE);
g_return_val_if_fail(ifindex > 0, FALSE);
g_return_val_if_fail(eee, FALSE);
return nmp_utils_ethtool_get_eee(ifindex, eee);
return klass->ethtool_get_pause(self, ifindex, pause);
}
gboolean
@ -3738,8 +3725,20 @@ nm_platform_ethtool_set_pause(NMPlatform *self, int ifindex, const NMEthtoolPaus
_CHECK_SELF_NETNS(self, klass, netns, FALSE);
g_return_val_if_fail(ifindex > 0, FALSE);
g_return_val_if_fail(pause, FALSE);
return nmp_utils_ethtool_set_pause(ifindex, pause);
return klass->ethtool_set_pause(self, ifindex, pause);
}
gboolean
nm_platform_ethtool_get_eee(NMPlatform *self, int ifindex, NMEthtoolEEEState *eee)
{
_CHECK_SELF_NETNS(self, klass, netns, FALSE);
g_return_val_if_fail(ifindex > 0, FALSE);
g_return_val_if_fail(eee, FALSE);
return klass->ethtool_get_eee(self, ifindex, eee);
}
gboolean
@ -3748,8 +3747,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_utils_ethtool_set_eee(ifindex, eee);
return klass->ethtool_set_eee(self, ifindex, eee);
}
/*****************************************************************************/

View file

@ -1346,6 +1346,12 @@ typedef struct {
GPtrArray *(*mptcp_addrs_dump)(NMPlatform *self);
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);
gboolean (*ethtool_get_ring)(NMPlatform *self, int ifindex, NMEthtoolRingState *ring);
gboolean (*ethtool_set_ring)(NMPlatform *self, int ifindex, const NMEthtoolRingState *ring);
} NMPlatformClass;
/* NMPlatform signals
@ -2631,7 +2637,7 @@ gboolean nm_platform_ethtool_get_link_settings(NMPlatform *self,
guint32 *out_speed,
NMPlatformLinkDuplexType *out_duplex);
NMEthtoolFeatureStates *nm_platform_ethtool_get_link_features(NMPlatform *self, int ifindex);
NMEthtoolFeatureStates *nm_platform_ethtool_get_features(NMPlatform *self, int ifindex);
gboolean nm_platform_ethtool_set_features(
NMPlatform *self,
int ifindex,
@ -2639,22 +2645,20 @@ gboolean nm_platform_ethtool_set_features(
const NMOptionBool *requested /* indexed by NMEthtoolID - _NM_ETHTOOL_ID_FEATURE_FIRST */,
gboolean do_set /* or reset */);
gboolean nm_platform_ethtool_get_link_coalesce(NMPlatform *self,
int ifindex,
NMEthtoolCoalesceState *coalesce);
gboolean
nm_platform_ethtool_get_coalesce(NMPlatform *self, int ifindex, NMEthtoolCoalesceState *coalesce);
gboolean nm_platform_ethtool_set_coalesce(NMPlatform *self,
int ifindex,
const NMEthtoolCoalesceState *coalesce);
gboolean nm_platform_ethtool_get_link_ring(NMPlatform *self, int ifindex, NMEthtoolRingState *ring);
gboolean nm_platform_ethtool_get_ring(NMPlatform *self, int ifindex, NMEthtoolRingState *ring);
gboolean
nm_platform_ethtool_set_ring(NMPlatform *self, int ifindex, const NMEthtoolRingState *ring);
gboolean nm_platform_ethtool_get_link_channels(NMPlatform *self,
int ifindex,
NMEthtoolChannelsState *channels);
gboolean
nm_platform_ethtool_get_channels(NMPlatform *self, int ifindex, NMEthtoolChannelsState *channels);
gboolean nm_platform_ethtool_set_channels(NMPlatform *self,
int ifindex,
@ -2664,10 +2668,9 @@ gboolean nm_platform_ethtool_get_fec_mode(NMPlatform *self, int ifindex, uint32_
gboolean nm_platform_ethtool_set_fec_mode(NMPlatform *self, int ifindex, uint32_t fec_mode);
gboolean
nm_platform_ethtool_get_link_pause(NMPlatform *self, int ifindex, NMEthtoolPauseState *pause);
gboolean nm_platform_ethtool_get_pause(NMPlatform *self, int ifindex, NMEthtoolPauseState *pause);
gboolean nm_platform_ethtool_get_link_eee(NMPlatform *self, int ifindex, NMEthtoolEEEState *eee);
gboolean nm_platform_ethtool_get_eee(NMPlatform *self, int ifindex, NMEthtoolEEEState *eee);
gboolean
nm_platform_ethtool_set_pause(NMPlatform *self, int ifindex, const NMEthtoolPauseState *pause);

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,55 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#ifndef __NMP_ETHTOOL_IOCTL_H__
#define __NMP_ETHTOOL_IOCTL_H__
#include "libnm-platform/nmp-base.h"
#include "libnm-platform/nm-netlink.h"
gboolean nmp_ethtool_ioctl_supports_carrier_detect(int ifindex);
gboolean nmp_ethtool_ioctl_supports_vlans(int ifindex);
int nmp_ethtool_ioctl_get_peer_ifindex(int ifindex);
gboolean nmp_ethtool_ioctl_get_wake_on_lan(int ifindex);
gboolean nmp_ethtool_ioctl_set_wake_on_lan(int ifindex,
_NMSettingWiredWakeOnLan wol,
const char *wol_password);
gboolean nmp_ethtool_ioctl_get_link_settings(int ifindex,
gboolean *out_autoneg,
guint32 *out_speed,
NMPlatformLinkDuplexType *out_duplex);
gboolean nmp_ethtool_ioctl_set_link_settings(int ifindex,
gboolean autoneg,
guint32 speed,
NMPlatformLinkDuplexType duplex);
gboolean nmp_ethtool_ioctl_get_permanent_address(int ifindex, guint8 *buf, size_t *length);
gboolean nmp_ethtool_ioctl_get_driver_info(int ifindex, NMPUtilsEthtoolDriverInfo *data);
NMEthtoolFeatureStates *nmp_ethtool_ioctl_get_features(int ifindex);
gboolean nmp_ethtool_ioctl_set_features(
int ifindex,
const NMEthtoolFeatureStates *features,
const NMOptionBool *requested /* indexed by NMEthtoolID - _NM_ETHTOOL_ID_FEATURE_FIRST */,
gboolean do_set /* or reset */);
gboolean nmp_ethtool_ioctl_get_coalesce(int ifindex, NMEthtoolCoalesceState *coalesce);
gboolean nmp_ethtool_ioctl_set_coalesce(int ifindex, const NMEthtoolCoalesceState *coalesce);
gboolean nmp_ethtool_ioctl_get_channels(int ifindex, NMEthtoolChannelsState *channels);
gboolean nmp_ethtool_ioctl_set_channels(int ifindex, const NMEthtoolChannelsState *channels);
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);
gboolean nmp_mii_ioctl_supports_carrier_detect(int ifindex);
#endif /* __NMP_ETHTOOL_IOCTL_H__ */

View file

@ -0,0 +1,559 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "libnm-glib-aux/nm-default-glib-i18n-lib.h"
#include "nmp-ethtool.h"
#include "libnm-platform/nm-platform.h"
#include "libnm-log-core/nm-logging.h"
enum {
ETHTOOL_A_HEADER_UNSPEC,
ETHTOOL_A_HEADER_DEV_INDEX, /* u32 */
ETHTOOL_A_HEADER_DEV_NAME, /* string */
ETHTOOL_A_HEADER_FLAGS, /* u32 - ETHTOOL_FLAG_* */
ETHTOOL_A_HEADER_PHY_INDEX, /* u32 */
/* add new constants above here */
__ETHTOOL_A_HEADER_CNT,
ETHTOOL_A_HEADER_MAX = __ETHTOOL_A_HEADER_CNT - 1
};
enum {
ETHTOOL_MSG_USER_NONE = 0,
ETHTOOL_MSG_STRSET_GET = 1,
ETHTOOL_MSG_LINKINFO_GET,
ETHTOOL_MSG_LINKINFO_SET,
ETHTOOL_MSG_LINKMODES_GET,
ETHTOOL_MSG_LINKMODES_SET,
ETHTOOL_MSG_LINKSTATE_GET,
ETHTOOL_MSG_DEBUG_GET,
ETHTOOL_MSG_DEBUG_SET,
ETHTOOL_MSG_WOL_GET,
ETHTOOL_MSG_WOL_SET,
ETHTOOL_MSG_FEATURES_GET,
ETHTOOL_MSG_FEATURES_SET,
ETHTOOL_MSG_PRIVFLAGS_GET,
ETHTOOL_MSG_PRIVFLAGS_SET,
ETHTOOL_MSG_RINGS_GET,
ETHTOOL_MSG_RINGS_SET,
ETHTOOL_MSG_CHANNELS_GET,
ETHTOOL_MSG_CHANNELS_SET,
ETHTOOL_MSG_COALESCE_GET,
ETHTOOL_MSG_COALESCE_SET,
ETHTOOL_MSG_PAUSE_GET,
ETHTOOL_MSG_PAUSE_SET,
ETHTOOL_MSG_EEE_GET,
ETHTOOL_MSG_EEE_SET,
ETHTOOL_MSG_TSINFO_GET,
ETHTOOL_MSG_CABLE_TEST_ACT,
ETHTOOL_MSG_CABLE_TEST_TDR_ACT,
ETHTOOL_MSG_TUNNEL_INFO_GET,
ETHTOOL_MSG_FEC_GET,
ETHTOOL_MSG_FEC_SET,
/* add new constants above here */
__ETHTOOL_MSG_USER_CNT,
ETHTOOL_MSG_USER_MAX = __ETHTOOL_MSG_USER_CNT - 1
};
#define ETHTOOL_GENL_VERSION 1
#define _NMLOG_DOMAIN LOGD_PLATFORM
#define _NMLOG_PREFIX_NAME "ethtool"
#define _NMLOG(_level, ...) \
G_STMT_START \
{ \
int _ifindex = ifindex; \
\
nm_log((_level), \
(_NMLOG_DOMAIN), \
NULL, \
NULL, \
"%s[%d]: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \
_NMLOG_PREFIX_NAME, \
_ifindex _NM_UTILS_MACRO_REST(__VA_ARGS__)); \
} \
G_STMT_END
#define CB_RESULT_PENDING 0
#define CB_RESULT_OK 1
static int
ack_cb_handler(const struct nl_msg *msg, void *data)
{
int *result = data;
*result = CB_RESULT_OK;
return NL_STOP;
}
static int
finish_cb_handler(const struct nl_msg *msg, void *data)
{
int *result = data;
*result = CB_RESULT_OK;
return NL_SKIP;
}
static int
err_cb_handler(const struct sockaddr_nl *nla, const struct nlmsgerr *err, void *data)
{
void **args = data;
int *result = args[0];
char **err_msg = args[1];
const char *extack_msg = NULL;
*result = err->error;
nlmsg_parse_error(nlmsg_undata(err), &extack_msg);
if (err_msg)
*err_msg = g_strdup(extack_msg ?: nm_strerror(err->error));
return NL_SKIP;
}
static int
ethtool_send_and_recv(struct nl_sock *sock,
int ifindex,
struct nl_msg *msg,
int (*valid_handler)(const struct nl_msg *, void *),
void *valid_data,
char **err_msg,
const char *log_prefix)
{
int nle;
int cb_result = CB_RESULT_PENDING;
void *err_arg[] = {&cb_result, err_msg};
const struct nl_cb cb = {
.err_cb = err_cb_handler,
.err_arg = err_arg,
.finish_cb = finish_cb_handler,
.finish_arg = &cb_result,
.ack_cb = ack_cb_handler,
.ack_arg = &cb_result,
.valid_cb = valid_handler,
.valid_arg = valid_data,
};
g_return_val_if_fail(msg, -ENOMEM);
if (err_msg)
*err_msg = NULL;
nle = nl_send_auto(sock, msg);
if (nle < 0)
goto out;
while (cb_result == CB_RESULT_PENDING) {
nle = nl_recvmsgs(sock, &cb);
if (nle < 0 && nle != -EAGAIN) {
break;
}
}
out:
if (nle < 0 && err_msg && *err_msg == NULL)
*err_msg = strdup(nm_strerror(nle));
if (nle >= 0 && cb_result < 0)
nle = cb_result;
if (nle < 0) {
_LOGT("%s: netlink error: %d (%s)", log_prefix, nle, err_msg && *err_msg ? *err_msg : "");
}
return nle;
}
static struct nl_msg *
ethtool_create_msg(guint16 family_id,
int ifindex,
guint8 cmd,
int header_attr,
const char *log_prefix)
{
nm_auto_nlmsg struct nl_msg *msg = NULL;
struct nlattr *nest_header;
if (family_id == 0) {
_LOGT("%s: ethtool genl family not found", log_prefix);
return NULL;
}
msg = nlmsg_alloc(nlmsg_total_size(GENL_HDRLEN) + 200);
if (!genlmsg_put(msg,
NL_AUTO_PORT,
NL_AUTO_SEQ,
family_id,
0,
NLM_F_REQUEST,
cmd,
ETHTOOL_GENL_VERSION))
goto nla_put_failure;
nest_header = nla_nest_start(msg, header_attr);
NLA_PUT_U32(msg, ETHTOOL_A_HEADER_DEV_INDEX, (guint32) ifindex);
NLA_NEST_END(msg, nest_header);
return g_steal_pointer(&msg);
nla_put_failure:
g_return_val_if_reached(NULL);
}
/*****************************************************************************/
/* PAUSE */
/*****************************************************************************/
enum {
ETHTOOL_A_PAUSE_UNSPEC,
ETHTOOL_A_PAUSE_HEADER,
ETHTOOL_A_PAUSE_AUTONEG,
ETHTOOL_A_PAUSE_RX,
ETHTOOL_A_PAUSE_TX,
__ETHTOOL_A_PAUSE_CNT,
ETHTOOL_A_PAUSE_MAX = (__ETHTOOL_A_PAUSE_CNT - 1)
};
static int
ethtool_parse_pause(const struct nl_msg *msg, void *data)
{
NMEthtoolPauseState *pause = data;
static const struct nla_policy policy[] = {
[ETHTOOL_A_PAUSE_AUTONEG] = {.type = NLA_U8},
[ETHTOOL_A_PAUSE_RX] = {.type = NLA_U8},
[ETHTOOL_A_PAUSE_TX] = {.type = NLA_U8},
};
struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
struct nlattr *tb[G_N_ELEMENTS(policy)];
*pause = (NMEthtoolPauseState) {};
if (nla_parse_arr(tb, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), policy) < 0)
return NL_SKIP;
if (tb[ETHTOOL_A_PAUSE_AUTONEG])
pause->autoneg = !!nla_get_u8(tb[ETHTOOL_A_PAUSE_AUTONEG]);
if (tb[ETHTOOL_A_PAUSE_RX])
pause->rx = !!nla_get_u8(tb[ETHTOOL_A_PAUSE_RX]);
if (tb[ETHTOOL_A_PAUSE_TX])
pause->tx = !!nla_get_u8(tb[ETHTOOL_A_PAUSE_TX]);
return NL_OK;
}
gboolean
nmp_ethtool_get_pause(struct nl_sock *genl_sock,
guint16 family_id,
int ifindex,
NMEthtoolPauseState *pause)
{
nm_auto_nlmsg struct nl_msg *msg = NULL;
gs_free char *err_msg = NULL;
int r;
g_return_val_if_fail(pause, FALSE);
_LOGT("get-pause: start");
*pause = (NMEthtoolPauseState) {};
msg = ethtool_create_msg(family_id,
ifindex,
ETHTOOL_MSG_PAUSE_GET,
ETHTOOL_A_PAUSE_HEADER,
"get-pause");
if (!msg)
return FALSE;
r = ethtool_send_and_recv(genl_sock,
ifindex,
msg,
ethtool_parse_pause,
pause,
&err_msg,
"get-pause");
if (r < 0)
return FALSE;
_LOGT("get-pause: autoneg %d rx %d tx %d", pause->autoneg, pause->rx, pause->tx);
return TRUE;
}
gboolean
nmp_ethtool_set_pause(struct nl_sock *genl_sock,
guint16 family_id,
int ifindex,
const NMEthtoolPauseState *pause)
{
nm_auto_nlmsg struct nl_msg *msg = NULL;
gs_free char *err_msg = NULL;
int r;
g_return_val_if_fail(pause, FALSE);
_LOGT("set-pause: autoneg %d rx %d tx %d", pause->autoneg, pause->rx, pause->tx);
msg = ethtool_create_msg(family_id,
ifindex,
ETHTOOL_MSG_PAUSE_SET,
ETHTOOL_A_PAUSE_HEADER,
"set-pause");
if (!msg)
return FALSE;
NLA_PUT_U8(msg, ETHTOOL_A_PAUSE_AUTONEG, pause->autoneg);
NLA_PUT_U8(msg, ETHTOOL_A_PAUSE_RX, pause->rx);
NLA_PUT_U8(msg, ETHTOOL_A_PAUSE_TX, pause->tx);
r = ethtool_send_and_recv(genl_sock, ifindex, msg, NULL, NULL, &err_msg, "set-pause");
if (r < 0)
return FALSE;
_LOGT("set-pause: succeeded");
return TRUE;
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);
}
/*****************************************************************************/
/* 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);
}

View file

@ -0,0 +1,35 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#ifndef __NMP_ETHTOOL_H__
#define __NMP_ETHTOOL_H__
#include "libnm-platform/nmp-base.h"
#include "libnm-platform/nm-netlink.h"
gboolean nmp_ethtool_get_pause(struct nl_sock *genl_sock,
guint16 family_id,
int ifindex,
NMEthtoolPauseState *pause);
gboolean nmp_ethtool_set_pause(struct nl_sock *genl_sock,
guint16 family_id,
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);
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__ */

View file

@ -16,6 +16,7 @@
#include "libnm-platform/nm-platform-utils.h"
#include "libnm-platform/wifi/nm-wifi-utils.h"
#include "libnm-platform/wpan/nm-wpan-utils.h"
#include "libnm-platform/nmp-ethtool-ioctl.h"
/*****************************************************************************/
@ -647,7 +648,7 @@ _link_get_driver(struct udev_device *udevice, const char *kind, int ifindex)
if (ifindex > 0) {
NMPUtilsEthtoolDriverInfo driver_info;
if (nmp_utils_ethtool_get_driver_info(ifindex, &driver_info)) {
if (nmp_ethtool_ioctl_get_driver_info(ifindex, &driver_info)) {
if (driver_info.driver[0])
return g_intern_string(driver_info.driver);
}

View file

@ -11,7 +11,6 @@
#include <arpa/inet.h>
#include <linux/if_ether.h>
#include <linux/if_infiniband.h>
#include <linux/ethtool.h>
#include "libnm-core-aux-intern/nm-common-macros.h"
#include "libnm-glib-aux/nm-enum-utils.h"