mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-01-03 22:10:14 +01:00
merge: branch 'bg/ethtool-netlink'
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/2169
This commit is contained in:
commit
7b2924b762
16 changed files with 2419 additions and 1895 deletions
|
|
@ -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
|
||||
-------------
|
||||
|
||||
|
|
|
|||
|
|
@ -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)");
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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, ðtool_driver_info)) {
|
||||
if (!nmp_ethtool_ioctl_get_driver_info(self->ifindex, ðtool_driver_info)) {
|
||||
g_set_error(error,
|
||||
NM_UTILS_ERROR,
|
||||
NM_UTILS_ERROR_UNKNOWN,
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
1603
src/libnm-platform/nmp-ethtool-ioctl.c
Normal file
1603
src/libnm-platform/nmp-ethtool-ioctl.c
Normal file
File diff suppressed because it is too large
Load diff
55
src/libnm-platform/nmp-ethtool-ioctl.h
Normal file
55
src/libnm-platform/nmp-ethtool-ioctl.h
Normal 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__ */
|
||||
559
src/libnm-platform/nmp-ethtool.c
Normal file
559
src/libnm-platform/nmp-ethtool.c
Normal 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);
|
||||
}
|
||||
35
src/libnm-platform/nmp-ethtool.h
Normal file
35
src/libnm-platform/nmp-ethtool.h
Normal 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__ */
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue