summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2021-01-10 09:55:06 +0100
committerThomas Haller <thaller@redhat.com>2021-01-14 10:31:15 +0100
commit3eaaf2d91ec2e2e96e05c1a789181d87e08d053a (patch)
tree022ab3a6e622d18cf17dd5fbf565d5f13649f587 /src
parent884f56604794a26c20cdbaab0facf2ce3626b3ec (diff)
downloadNetworkManager-th/shared-nm-platform.tar.gz
platform: move "nm-platform-utils.[hc]" to "shared/nm-platform" libraryth/shared-nm-platform
By now it has no further dependencies on libnm-core or NetworkManager core. Make it part of "shared/nm-platform" library.
Diffstat (limited to 'src')
-rw-r--r--src/devices/nm-device-ethernet.c2
-rw-r--r--src/devices/nm-device.c2
-rw-r--r--src/meson.build1
-rw-r--r--src/nm-iface-helper.c2
-rw-r--r--src/nm-ip4-config.c2
-rw-r--r--src/nm-ip6-config.c2
-rw-r--r--src/nm-l3-config-data.c2
-rw-r--r--src/platform/nm-fake-platform.c2
-rw-r--r--src/platform/nm-linux-platform.c2
-rw-r--r--src/platform/nm-platform-utils.c1792
-rw-r--r--src/platform/nm-platform-utils.h73
-rw-r--r--src/platform/nm-platform.c2
-rw-r--r--src/platform/nmp-object.c2
-rw-r--r--src/platform/tests/test-link.c2
-rw-r--r--src/platform/tests/test-platform-general.c2
-rw-r--r--src/platform/tests/test-route.c2
-rw-r--r--src/platform/tests/test-tc.c2
-rw-r--r--src/platform/wifi/nm-wifi-utils-nl80211.c2
-rw-r--r--src/platform/wifi/nm-wifi-utils-wext.c2
-rw-r--r--src/platform/wifi/nm-wifi-utils.c2
-rw-r--r--src/platform/wpan/nm-wpan-utils.c2
21 files changed, 18 insertions, 1884 deletions
diff --git a/src/devices/nm-device-ethernet.c b/src/devices/nm-device-ethernet.c
index 05f5fe1e8d..f67baead46 100644
--- a/src/devices/nm-device-ethernet.c
+++ b/src/devices/nm-device-ethernet.c
@@ -25,7 +25,7 @@
#include "ppp/nm-ppp-manager-call.h"
#include "ppp/nm-ppp-status.h"
#include "platform/nm-platform.h"
-#include "platform/nm-platform-utils.h"
+#include "nm-platform/nm-platform-utils.h"
#include "nm-dcb.h"
#include "settings/nm-settings-connection.h"
#include "nm-config.h"
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index 53c42dbedf..8316107123 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -36,7 +36,7 @@
#include "NetworkManagerUtils.h"
#include "nm-manager.h"
#include "platform/nm-platform.h"
-#include "platform/nm-platform-utils.h"
+#include "nm-platform/nm-platform-utils.h"
#include "platform/nmp-object.h"
#include "platform/nmp-rules-manager.h"
#include "ndisc/nm-ndisc.h"
diff --git a/src/meson.build b/src/meson.build
index 8cb5089cad..8c0c141c29 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -37,7 +37,6 @@ sources = files(
'platform/wpan/nm-wpan-utils.c',
'platform/nm-linux-platform.c',
'platform/nm-platform.c',
- 'platform/nm-platform-utils.c',
'platform/nmp-object.c',
'platform/nmp-rules-manager.c',
'main-utils.c',
diff --git a/src/nm-iface-helper.c b/src/nm-iface-helper.c
index 8fc30adb8b..42483cf756 100644
--- a/src/nm-iface-helper.c
+++ b/src/nm-iface-helper.c
@@ -21,7 +21,7 @@
#include "main-utils.h"
#include "NetworkManagerUtils.h"
#include "platform/nm-linux-platform.h"
-#include "platform/nm-platform-utils.h"
+#include "nm-platform/nm-platform-utils.h"
#include "dhcp/nm-dhcp-manager.h"
#include "ndisc/nm-ndisc.h"
#include "ndisc/nm-lndp-ndisc.h"
diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c
index b881871c5a..8014549f4d 100644
--- a/src/nm-ip4-config.c
+++ b/src/nm-ip4-config.c
@@ -17,7 +17,7 @@
#include "nm-utils.h"
#include "platform/nmp-object.h"
#include "platform/nm-platform.h"
-#include "platform/nm-platform-utils.h"
+#include "nm-platform/nm-platform-utils.h"
#include "NetworkManagerUtils.h"
#include "nm-core-internal.h"
#include "nm-dbus-object.h"
diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c
index 0be98e5fe6..eeb69946a4 100644
--- a/src/nm-ip6-config.c
+++ b/src/nm-ip6-config.c
@@ -18,7 +18,7 @@
#include "nm-utils.h"
#include "platform/nmp-object.h"
#include "platform/nm-platform.h"
-#include "platform/nm-platform-utils.h"
+#include "nm-platform/nm-platform-utils.h"
#include "nm-core-internal.h"
#include "NetworkManagerUtils.h"
#include "nm-ip4-config.h"
diff --git a/src/nm-l3-config-data.c b/src/nm-l3-config-data.c
index daff7312db..0f689d409b 100644
--- a/src/nm-l3-config-data.c
+++ b/src/nm-l3-config-data.c
@@ -11,7 +11,7 @@
#include "nm-glib-aux/nm-enum-utils.h"
#include "nm-core-internal.h"
#include "platform/nm-platform.h"
-#include "platform/nm-platform-utils.h"
+#include "nm-platform/nm-platform-utils.h"
#include "platform/nmp-object.h"
#include "NetworkManagerUtils.h"
diff --git a/src/platform/nm-fake-platform.c b/src/platform/nm-fake-platform.c
index 21f1e92465..fbd3e3fbc7 100644
--- a/src/platform/nm-fake-platform.c
+++ b/src/platform/nm-fake-platform.c
@@ -16,7 +16,7 @@
#include "nm-utils.h"
#include "nm-core-utils.h"
-#include "nm-platform-utils.h"
+#include "nm-platform/nm-platform-utils.h"
#include "nm-platform-private.h"
#include "nmp-object.h"
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
index e21c31e0a6..3d992704eb 100644
--- a/src/platform/nm-linux-platform.c
+++ b/src/platform/nm-linux-platform.c
@@ -44,7 +44,7 @@
#include "nm-core-utils.h"
#include "nmp-object.h"
#include "nm-platform/nmp-netns.h"
-#include "nm-platform-utils.h"
+#include "nm-platform/nm-platform-utils.h"
#include "nm-platform-private.h"
#include "wifi/nm-wifi-utils.h"
#include "wifi/nm-wifi-utils-wext.h"
diff --git a/src/platform/nm-platform-utils.c b/src/platform/nm-platform-utils.c
deleted file mode 100644
index 0947ef4c81..0000000000
--- a/src/platform/nm-platform-utils.c
+++ /dev/null
@@ -1,1792 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2015 Red Hat, Inc.
- */
-
-#include "nm-default.h"
-
-#include "nm-platform-utils.h"
-
-#include <unistd.h>
-#include <sys/ioctl.h>
-#include <linux/ethtool.h>
-#include <linux/sockios.h>
-#include <linux/mii.h>
-#include <linux/if.h>
-#include <linux/version.h>
-#include <linux/rtnetlink.h>
-#include <fcntl.h>
-#include <libudev.h>
-
-#include "nm-base/nm-ethtool-base.h"
-
-/*****************************************************************************/
-
-#define ONOFF(bool_val) ((bool_val) ? "on" : "off")
-
-/******************************************************************************
- * utils
- *****************************************************************************/
-
-extern char *if_indextoname(unsigned __ifindex, char *__ifname);
-unsigned if_nametoindex(const char *__ifname);
-
-const char *
-nmp_utils_if_indextoname(int ifindex, char *out_ifname /*IFNAMSIZ*/)
-{
- g_return_val_if_fail(ifindex > 0, NULL);
- g_return_val_if_fail(out_ifname, NULL);
-
- return if_indextoname(ifindex, out_ifname);
-}
-
-int
-nmp_utils_if_nametoindex(const char *ifname)
-{
- g_return_val_if_fail(ifname, 0);
-
- return if_nametoindex(ifname);
-}
-
-/*****************************************************************************/
-
-NM_UTILS_LOOKUP_STR_DEFINE(nm_platform_link_duplex_type_to_string,
- NMPlatformLinkDuplexType,
- NM_UTILS_LOOKUP_DEFAULT_WARN(NULL),
- NM_UTILS_LOOKUP_STR_ITEM(NM_PLATFORM_LINK_DUPLEX_UNKNOWN, "unknown"),
- NM_UTILS_LOOKUP_STR_ITEM(NM_PLATFORM_LINK_DUPLEX_FULL, "full"),
- NM_UTILS_LOOKUP_STR_ITEM(NM_PLATFORM_LINK_DUPLEX_HALF, "half"), );
-
-/*****************************************************************************/
-
-typedef struct {
- int fd;
- const int ifindex;
- char ifname[IFNAMSIZ];
-} SocketHandle;
-
-#define SOCKET_HANDLE_INIT(_ifindex) \
- { \
- .fd = -1, .ifindex = (_ifindex), \
- }
-
-static void
-_nm_auto_socket_handle(SocketHandle *shandle)
-{
- if (shandle->fd >= 0)
- nm_close(shandle->fd);
-}
-
-#define nm_auto_socket_handle nm_auto(_nm_auto_socket_handle)
-
-/*****************************************************************************/
-
-typedef enum {
- IOCTL_CALL_DATA_TYPE_NONE,
- IOCTL_CALL_DATA_TYPE_IFRDATA,
- IOCTL_CALL_DATA_TYPE_IFRU,
-} IoctlCallDataType;
-
-static int
-_ioctl_call(const char * log_ioctl_type,
- const char * log_subtype,
- unsigned long int ioctl_request,
- int ifindex,
- int * inout_fd,
- char * inout_ifname,
- IoctlCallDataType edata_type,
- gpointer edata,
- gsize edata_size,
- struct ifreq * out_ifreq)
-{
- nm_auto_close int fd_close = -1;
- int fd;
- int r;
- gpointer edata_backup = NULL;
- gs_free gpointer edata_backup_free = NULL;
- guint try_count;
- char known_ifnames[2][IFNAMSIZ];
- const char * failure_reason = NULL;
- struct ifreq ifr;
-
- nm_assert(ifindex > 0);
- nm_assert(NM_IN_SET(edata_type,
- IOCTL_CALL_DATA_TYPE_NONE,
- IOCTL_CALL_DATA_TYPE_IFRDATA,
- IOCTL_CALL_DATA_TYPE_IFRU));
- nm_assert(edata_type != IOCTL_CALL_DATA_TYPE_NONE || edata_size == 0);
- nm_assert(edata_type != IOCTL_CALL_DATA_TYPE_IFRDATA || edata_size > 0);
- nm_assert(edata_type != IOCTL_CALL_DATA_TYPE_IFRU
- || (edata_size > 0 && edata_size <= sizeof(ifr.ifr_ifru)));
- nm_assert(edata_size == 0 || edata);
-
- /* open a file descriptor (or use the one provided). */
- if (inout_fd && *inout_fd >= 0)
- fd = *inout_fd;
- else {
- fd = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
- if (fd < 0) {
- r = -NM_ERRNO_NATIVE(errno);
- failure_reason = "failed creating socket or ioctl";
- goto out;
- }
- if (inout_fd)
- *inout_fd = fd;
- else
- fd_close = fd;
- }
-
- /* resolve the ifindex to name (or use the one provided). */
- if (inout_ifname && inout_ifname[0])
- nm_utils_ifname_cpy(known_ifnames[0], inout_ifname);
- else {
- if (!nmp_utils_if_indextoname(ifindex, known_ifnames[0])) {
- failure_reason = "cannot resolve ifindex";
- r = -ENODEV;
- goto out;
- }
- if (inout_ifname)
- nm_utils_ifname_cpy(inout_ifname, known_ifnames[0]);
- }
-
- /* we might need to retry the request. Backup edata so that we can
- * restore it on retry. */
- if (edata_size > 0)
- edata_backup = nm_memdup_maybe_a(500, edata, edata_size, &edata_backup_free);
-
- try_count = 0;
-
-again:
-{
- const char *ifname = known_ifnames[try_count % 2];
-
- nm_assert(ifindex > 0);
- nm_assert(ifname && nm_utils_ifname_valid_kernel(ifname, NULL));
- nm_assert(fd >= 0);
-
- memset(&ifr, 0, sizeof(ifr));
- nm_utils_ifname_cpy(ifr.ifr_name, ifname);
- if (edata_type == IOCTL_CALL_DATA_TYPE_IFRDATA)
- ifr.ifr_data = edata;
- else if (edata_type == IOCTL_CALL_DATA_TYPE_IFRU)
- memcpy(&ifr.ifr_ifru, edata, NM_MIN(edata_size, sizeof(ifr.ifr_ifru)));
-
- if (ioctl(fd, ioctl_request, &ifr) < 0) {
- r = -NM_ERRNO_NATIVE(errno);
- nm_log_trace(LOGD_PLATFORM,
- "%s[%d]: %s, %s: failed: %s",
- log_ioctl_type,
- ifindex,
- log_subtype,
- ifname,
- nm_strerror_native(-r));
- } else {
- r = 0;
- nm_log_trace(LOGD_PLATFORM,
- "%s[%d]: %s, %s: success",
- log_ioctl_type,
- ifindex,
- log_subtype,
- ifname);
- }
-}
-
- try_count++;
-
- /* resolve the name again to see whether the ifindex still has the same name. */
- if (!nmp_utils_if_indextoname(ifindex, known_ifnames[try_count % 2])) {
- /* we could not find the ifindex again. Probably the device just got
- * removed.
- *
- * In both cases we return the error code we got from ioctl above.
- * Either it failed because the device was gone already or it still
- * managed to complete the call. In both cases, the error code is good. */
- failure_reason =
- "cannot resolve ifindex after ioctl call. Probably the device was just removed";
- goto out;
- }
-
- /* check whether the ifname changed in the meantime. If yes, would render the result
- * invalid. Note that this cannot detect every race regarding renames, for example:
- *
- * - if_indextoname(#10) gives eth0
- * - rename(#10) => eth0_tmp
- * - rename(#11) => eth0
- * - ioctl(eth0) (wrongly fetching #11, formerly eth1)
- * - rename(#11) => eth_something
- * - rename(#10) => eth0
- * - if_indextoname(#10) gives eth0
- */
- if (!nm_streq(known_ifnames[0], known_ifnames[1])) {
- gboolean retry;
-
- /* we detected a possible(!) rename.
- *
- * For getters it's straight forward to just retry the call.
- *
- * For setters we also always retry. If our previous call operated on the right device,
- * calling it again should have no bad effect (just setting the same thing more than once).
- *
- * The only potential bad thing is if there was a race involving swapping names, and we just
- * set the ioctl option on the wrong device. But then the bad thing already happenned and
- * we cannot detect it (nor do anything about it). At least, we can retry and set the
- * option on the right interface. */
- retry = (try_count < 5);
-
- nm_log_trace(LOGD_PLATFORM,
- "%s[%d]: %s: rename detected from \"%s\" to \"%s\". %s",
- log_ioctl_type,
- ifindex,
- log_subtype,
- known_ifnames[(try_count - 1) % 2],
- known_ifnames[try_count % 2],
- retry ? "Retry" : "No retry");
- if (inout_ifname)
- nm_utils_ifname_cpy(inout_ifname, known_ifnames[try_count % 2]);
- if (retry) {
- if (edata_size > 0)
- memcpy(edata, edata_backup, edata_size);
- goto again;
- }
- }
-
-out:
- if (failure_reason) {
- nm_log_trace(LOGD_PLATFORM,
- "%s[%d]: %s: %s: %s",
- log_ioctl_type,
- ifindex,
- log_subtype,
- failure_reason,
- r < 0 ? nm_strerror_native(-r) : "assume success");
- }
- if (r >= 0)
- NM_SET_OUT(out_ifreq, ifr);
- return r;
-}
-
-/******************************************************************************
- * ethtool
- *****************************************************************************/
-
-static NM_UTILS_ENUM2STR_DEFINE(_ethtool_cmd_to_string,
- guint32,
- NM_UTILS_ENUM2STR(ETHTOOL_GCOALESCE, "ETHTOOL_GCOALESCE"),
- NM_UTILS_ENUM2STR(ETHTOOL_GDRVINFO, "ETHTOOL_GDRVINFO"),
- NM_UTILS_ENUM2STR(ETHTOOL_GFEATURES, "ETHTOOL_GFEATURES"),
- NM_UTILS_ENUM2STR(ETHTOOL_GLINK, "ETHTOOL_GLINK"),
- NM_UTILS_ENUM2STR(ETHTOOL_GPERMADDR, "ETHTOOL_GPERMADDR"),
- NM_UTILS_ENUM2STR(ETHTOOL_GRINGPARAM, "ETHTOOL_GRINGPARAM"),
- NM_UTILS_ENUM2STR(ETHTOOL_GSET, "ETHTOOL_GSET"),
- NM_UTILS_ENUM2STR(ETHTOOL_GSSET_INFO, "ETHTOOL_GSSET_INFO"),
- NM_UTILS_ENUM2STR(ETHTOOL_GSTATS, "ETHTOOL_GSTATS"),
- NM_UTILS_ENUM2STR(ETHTOOL_GSTRINGS, "ETHTOOL_GSTRINGS"),
- NM_UTILS_ENUM2STR(ETHTOOL_GWOL, "ETHTOOL_GWOL"),
- NM_UTILS_ENUM2STR(ETHTOOL_SCOALESCE, "ETHTOOL_SCOALESCE"),
- NM_UTILS_ENUM2STR(ETHTOOL_SFEATURES, "ETHTOOL_SFEATURES"),
- NM_UTILS_ENUM2STR(ETHTOOL_SRINGPARAM, "ETHTOOL_SRINGPARAM"),
- NM_UTILS_ENUM2STR(ETHTOOL_SSET, "ETHTOOL_SSET"),
- NM_UTILS_ENUM2STR(ETHTOOL_SWOL, "ETHTOOL_SWOL"), );
-
-static const char *
-_ethtool_edata_to_string(gpointer edata, gsize edata_size, char *sbuf, gsize sbuf_len)
-{
- nm_assert(edata);
- nm_assert(edata_size >= sizeof(guint32));
- nm_assert((((intptr_t) edata) % _nm_alignof(guint32)) == 0);
-
- return _ethtool_cmd_to_string(*((guint32 *) edata), sbuf, sbuf_len);
-}
-
-/*****************************************************************************/
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27)
- #define ethtool_cmd_speed(pedata) ((pedata)->speed)
-
- #define ethtool_cmd_speed_set(pedata, speed) \
- G_STMT_START \
- { \
- (pedata)->speed = (guint16)(speed); \
- } \
- G_STMT_END
-#endif
-
-static int
-_ethtool_call_handle(SocketHandle *shandle, gpointer edata, gsize edata_size)
-{
- char sbuf[50];
-
- return _ioctl_call("ethtool",
- _ethtool_edata_to_string(edata, edata_size, sbuf, sizeof(sbuf)),
- SIOCETHTOOL,
- shandle->ifindex,
- &shandle->fd,
- shandle->ifname,
- IOCTL_CALL_DATA_TYPE_IFRDATA,
- edata,
- edata_size,
- NULL);
-}
-
-static int
-_ethtool_call_once(int ifindex, gpointer edata, gsize edata_size)
-{
- char sbuf[50];
-
- return _ioctl_call("ethtool",
- _ethtool_edata_to_string(edata, edata_size, sbuf, sizeof(sbuf)),
- SIOCETHTOOL,
- ifindex,
- NULL,
- NULL,
- IOCTL_CALL_DATA_TYPE_IFRDATA,
- edata,
- edata_size,
- NULL);
-}
-
-/*****************************************************************************/
-
-static struct ethtool_gstrings *
-ethtool_get_stringset(SocketHandle *shandle, int stringset_id)
-{
- struct {
- struct ethtool_sset_info info;
- guint32 sentinel;
- } sset_info = {
- .info.cmd = ETHTOOL_GSSET_INFO,
- .info.reserved = 0,
- .info.sset_mask = (1ULL << stringset_id),
- };
- const guint32 * pdata;
- gs_free struct ethtool_gstrings *gstrings = NULL;
- gsize gstrings_len;
- guint32 i, len;
-
- if (_ethtool_call_handle(shandle, &sset_info, sizeof(sset_info)) < 0)
- return NULL;
- if (!sset_info.info.sset_mask)
- return NULL;
-
- pdata = (guint32 *) sset_info.info.data;
-
- len = *pdata;
-
- gstrings_len = sizeof(*gstrings) + (len * ETH_GSTRING_LEN);
- gstrings = g_malloc0(gstrings_len);
- gstrings->cmd = ETHTOOL_GSTRINGS;
- gstrings->string_set = stringset_id;
- gstrings->len = len;
- if (gstrings->len > 0) {
- if (_ethtool_call_handle(shandle, gstrings, gstrings_len) < 0)
- return NULL;
- for (i = 0; i < gstrings->len; i++) {
- /* ensure NUL terminated */
- gstrings->data[i * ETH_GSTRING_LEN + (ETH_GSTRING_LEN - 1)] = '\0';
- }
- }
-
- return g_steal_pointer(&gstrings);
-}
-
-static int
-ethtool_gstrings_find(const struct ethtool_gstrings *gstrings, const char *needle)
-{
- guint32 i;
-
- /* ethtool_get_stringset() always ensures NUL terminated strings at ETH_GSTRING_LEN.
- * that means, we cannot possibly request longer names. */
- nm_assert(needle && strlen(needle) < ETH_GSTRING_LEN);
-
- for (i = 0; i < gstrings->len; i++) {
- if (nm_streq((char *) &gstrings->data[i * ETH_GSTRING_LEN], needle))
- return i;
- }
- return -1;
-}
-
-static int
-ethtool_get_stringset_index(SocketHandle *shandle, int stringset_id, const char *needle)
-{
- gs_free struct ethtool_gstrings *gstrings = NULL;
-
- /* ethtool_get_stringset() always ensures NUL terminated strings at ETH_GSTRING_LEN.
- * that means, we cannot possibly request longer names. */
- nm_assert(needle && strlen(needle) < ETH_GSTRING_LEN);
-
- gstrings = ethtool_get_stringset(shandle, stringset_id);
- if (gstrings)
- return ethtool_gstrings_find(gstrings, needle);
- return -1;
-}
-
-/*****************************************************************************/
-
-static const NMEthtoolFeatureInfo _ethtool_feature_infos[_NM_ETHTOOL_ID_FEATURE_NUM] = {
-#define ETHT_FEAT(eid, ...) \
- { \
- .ethtool_id = eid, .n_kernel_names = NM_NARG(__VA_ARGS__), \
- .kernel_names = ((const char *const[]){__VA_ARGS__}), \
- }
-
- /* the order does only matter for one thing: if it happens that more than one NMEthtoolID
- * reference the same kernel-name, then the one that is mentioned *later* will win in
- * case these NMEthtoolIDs are set. That mostly only makes sense for ethtool-ids which
- * refer to multiple features ("feature-tso"), while also having more specific ids
- * ("feature-tx-tcp-segmentation"). */
-
- /* names from ethtool utility, which are aliases for multiple features. */
- ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_SG, "tx-scatter-gather", "tx-scatter-gather-fraglist"),
- ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TSO,
- "tx-tcp-segmentation",
- "tx-tcp-ecn-segmentation",
- "tx-tcp-mangleid-segmentation",
- "tx-tcp6-segmentation"),
- ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX,
- "tx-checksum-ipv4",
- "tx-checksum-ip-generic",
- "tx-checksum-ipv6",
- "tx-checksum-fcoe-crc",
- "tx-checksum-sctp"),
-
- /* names from ethtool utility, which are aliases for one feature. */
- ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_GRO, "rx-gro"),
- ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_GSO, "tx-generic-segmentation"),
- ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_LRO, "rx-lro"),
- ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_NTUPLE, "rx-ntuple-filter"),
- ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_RX, "rx-checksum"),
- ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_RXHASH, "rx-hashing"),
- ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_RXVLAN, "rx-vlan-hw-parse"),
- ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TXVLAN, "tx-vlan-hw-insert"),
-
- /* names of features, as known by kernel. */
- ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_ESP_HW_OFFLOAD, "esp-hw-offload"),
- ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_ESP_TX_CSUM_HW_OFFLOAD, "esp-tx-csum-hw-offload"),
- ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_FCOE_MTU, "fcoe-mtu"),
- ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_HIGHDMA, "highdma"),
- ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_HW_TC_OFFLOAD, "hw-tc-offload"),
- ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_L2_FWD_OFFLOAD, "l2-fwd-offload"),
- ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_LOOPBACK, "loopback"),
- ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_RX_ALL, "rx-all"),
- ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_RX_FCS, "rx-fcs"),
- ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_RX_GRO_HW, "rx-gro-hw"),
- ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_RX_UDP_TUNNEL_PORT_OFFLOAD, "rx-udp_tunnel-port-offload"),
- ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_RX_VLAN_FILTER, "rx-vlan-filter"),
- ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_RX_VLAN_STAG_FILTER, "rx-vlan-stag-filter"),
- ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_RX_VLAN_STAG_HW_PARSE, "rx-vlan-stag-hw-parse"),
- ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TLS_HW_RECORD, "tls-hw-record"),
- ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TLS_HW_TX_OFFLOAD, "tls-hw-tx-offload"),
- ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_CHECKSUM_FCOE_CRC, "tx-checksum-fcoe-crc"),
- ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_CHECKSUM_IPV4, "tx-checksum-ipv4"),
- ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_CHECKSUM_IPV6, "tx-checksum-ipv6"),
- ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_CHECKSUM_IP_GENERIC, "tx-checksum-ip-generic"),
- ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_CHECKSUM_SCTP, "tx-checksum-sctp"),
- ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_ESP_SEGMENTATION, "tx-esp-segmentation"),
- ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_FCOE_SEGMENTATION, "tx-fcoe-segmentation"),
- ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_GRE_CSUM_SEGMENTATION, "tx-gre-csum-segmentation"),
- ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_GRE_SEGMENTATION, "tx-gre-segmentation"),
- ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_GSO_PARTIAL, "tx-gso-partial"),
- ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_GSO_ROBUST, "tx-gso-robust"),
- ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_IPXIP4_SEGMENTATION, "tx-ipxip4-segmentation"),
- ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_IPXIP6_SEGMENTATION, "tx-ipxip6-segmentation"),
- ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_NOCACHE_COPY, "tx-nocache-copy"),
- ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_SCATTER_GATHER, "tx-scatter-gather"),
- ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_SCATTER_GATHER_FRAGLIST, "tx-scatter-gather-fraglist"),
- ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_SCTP_SEGMENTATION, "tx-sctp-segmentation"),
- ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_TCP6_SEGMENTATION, "tx-tcp6-segmentation"),
- ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_TCP_ECN_SEGMENTATION, "tx-tcp-ecn-segmentation"),
- ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_TCP_MANGLEID_SEGMENTATION, "tx-tcp-mangleid-segmentation"),
- ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_TCP_SEGMENTATION, "tx-tcp-segmentation"),
- ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_UDP_SEGMENTATION, "tx-udp-segmentation"),
- ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_UDP_TNL_CSUM_SEGMENTATION, "tx-udp_tnl-csum-segmentation"),
- ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_UDP_TNL_SEGMENTATION, "tx-udp_tnl-segmentation"),
- ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_VLAN_STAG_HW_INSERT, "tx-vlan-stag-hw-insert"),
-};
-
-/* the number of kernel features that we handle. It essentially is the sum of all
- * kernel_names. So, all ethtool-ids that reference exactly one kernel-name
- * (_NM_ETHTOOL_ID_FEATURE_NUM) + some extra, for ethtool-ids that are aliases
- * for multiple kernel-names. */
-#define N_ETHTOOL_KERNEL_FEATURES (((guint) _NM_ETHTOOL_ID_FEATURE_NUM) + 8u)
-
-static void
-_ASSERT_ethtool_feature_infos(void)
-{
-#if NM_MORE_ASSERTS > 10
- guint i, k, n;
- bool found[_NM_ETHTOOL_ID_FEATURE_NUM] = {};
-
- G_STATIC_ASSERT_EXPR(G_N_ELEMENTS(_ethtool_feature_infos) == _NM_ETHTOOL_ID_FEATURE_NUM);
-
- n = 0;
- for (i = 0; i < G_N_ELEMENTS(_ethtool_feature_infos); i++) {
- NMEthtoolFeatureState kstate;
- const NMEthtoolFeatureInfo *inf = &_ethtool_feature_infos[i];
-
- g_assert(inf->ethtool_id >= _NM_ETHTOOL_ID_FEATURE_FIRST);
- g_assert(inf->ethtool_id <= _NM_ETHTOOL_ID_FEATURE_LAST);
- g_assert(inf->n_kernel_names > 0);
-
- for (k = 0; k < i; k++)
- g_assert(inf->ethtool_id != _ethtool_feature_infos[k].ethtool_id);
-
- g_assert(!found[_NM_ETHTOOL_ID_FEATURE_AS_IDX(inf->ethtool_id)]);
- found[_NM_ETHTOOL_ID_FEATURE_AS_IDX(inf->ethtool_id)] = TRUE;
-
- kstate.idx_kernel_name = inf->n_kernel_names - 1;
- g_assert((guint) kstate.idx_kernel_name == (guint)(inf->n_kernel_names - 1));
-
- n += inf->n_kernel_names;
- for (k = 0; k < inf->n_kernel_names; k++) {
- g_assert(nm_utils_strv_find_first((char **) inf->kernel_names, k, inf->kernel_names[k])
- < 0);
- }
- }
-
- for (i = 0; i < _NM_ETHTOOL_ID_FEATURE_NUM; i++)
- g_assert(found[i]);
-
- g_assert(n == N_ETHTOOL_KERNEL_FEATURES);
-#endif
-}
-
-static NMEthtoolFeatureStates *
-ethtool_get_features(SocketHandle *shandle)
-{
- gs_free NMEthtoolFeatureStates * states = NULL;
- gs_free struct ethtool_gstrings *ss_features = NULL;
-
- _ASSERT_ethtool_feature_infos();
-
- ss_features = ethtool_get_stringset(shandle, ETH_SS_FEATURES);
- if (!ss_features)
- return NULL;
-
- if (ss_features->len > 0) {
- gs_free struct ethtool_gfeatures * gfeatures_free = NULL;
- struct ethtool_gfeatures * gfeatures;
- gsize gfeatures_len;
- guint idx;
- const NMEthtoolFeatureState * states_list0 = NULL;
- const NMEthtoolFeatureState *const *states_plist0 = NULL;
- guint states_plist_n = 0;
-
- gfeatures_len = sizeof(struct ethtool_gfeatures)
- + (NM_DIV_ROUND_UP(ss_features->len, 32u) * sizeof(gfeatures->features[0]));
- gfeatures = nm_malloc0_maybe_a(300, gfeatures_len, &gfeatures_free);
- gfeatures->cmd = ETHTOOL_GFEATURES;
- gfeatures->size = NM_DIV_ROUND_UP(ss_features->len, 32u);
- if (_ethtool_call_handle(shandle, gfeatures, gfeatures_len) < 0)
- return NULL;
-
- for (idx = 0; idx < G_N_ELEMENTS(_ethtool_feature_infos); idx++) {
- const NMEthtoolFeatureInfo *info = &_ethtool_feature_infos[idx];
- guint idx_kernel_name;
-
- for (idx_kernel_name = 0; idx_kernel_name < info->n_kernel_names; idx_kernel_name++) {
- NMEthtoolFeatureState *kstate;
- const char * kernel_name = info->kernel_names[idx_kernel_name];
- int i_feature;
- guint i_block;
- guint32 i_flag;
-
- i_feature = ethtool_gstrings_find(ss_features, kernel_name);
- if (i_feature < 0)
- continue;
-
- i_block = ((guint) i_feature) / 32u;
- i_flag = (guint32)(1u << (((guint) i_feature) % 32u));
-
- if (!states) {
- states = g_malloc0(
- sizeof(NMEthtoolFeatureStates)
- + (N_ETHTOOL_KERNEL_FEATURES * sizeof(NMEthtoolFeatureState))
- + ((N_ETHTOOL_KERNEL_FEATURES + G_N_ELEMENTS(_ethtool_feature_infos))
- * sizeof(NMEthtoolFeatureState *)));
- states_list0 = &states->states_list[0];
- states_plist0 = (gpointer) &states_list0[N_ETHTOOL_KERNEL_FEATURES];
- states->n_ss_features = ss_features->len;
- }
-
- nm_assert(states->n_states < N_ETHTOOL_KERNEL_FEATURES);
- kstate = (NMEthtoolFeatureState *) &states_list0[states->n_states];
- states->n_states++;
-
- kstate->info = info;
- kstate->idx_ss_features = i_feature;
- kstate->idx_kernel_name = idx_kernel_name;
- kstate->available = !!(gfeatures->features[i_block].available & i_flag);
- kstate->requested = !!(gfeatures->features[i_block].requested & i_flag);
- kstate->active = !!(gfeatures->features[i_block].active & i_flag);
- kstate->never_changed = !!(gfeatures->features[i_block].never_changed & i_flag);
-
- nm_assert(states_plist_n
- < N_ETHTOOL_KERNEL_FEATURES + G_N_ELEMENTS(_ethtool_feature_infos));
-
- if (!states->states_indexed[_NM_ETHTOOL_ID_FEATURE_AS_IDX(info->ethtool_id)])
- states->states_indexed[_NM_ETHTOOL_ID_FEATURE_AS_IDX(info->ethtool_id)] =
- &states_plist0[states_plist_n];
- ((const NMEthtoolFeatureState **) states_plist0)[states_plist_n] = kstate;
- states_plist_n++;
- }
-
- if (states && states->states_indexed[_NM_ETHTOOL_ID_FEATURE_AS_IDX(info->ethtool_id)]) {
- nm_assert(states_plist_n
- < N_ETHTOOL_KERNEL_FEATURES + G_N_ELEMENTS(_ethtool_feature_infos));
- nm_assert(!states_plist0[states_plist_n]);
- states_plist_n++;
- }
- }
- }
-
- return g_steal_pointer(&states);
-}
-
-NMEthtoolFeatureStates *
-nmp_utils_ethtool_get_features(int ifindex)
-{
- nm_auto_socket_handle SocketHandle shandle = SOCKET_HANDLE_INIT(ifindex);
- NMEthtoolFeatureStates * features;
-
- g_return_val_if_fail(ifindex > 0, 0);
-
- features = ethtool_get_features(&shandle);
-
- if (!features) {
- nm_log_trace(LOGD_PLATFORM,
- "ethtool[%d]: %s: failure getting features",
- ifindex,
- "get-features");
- return NULL;
- }
-
- nm_log_trace(LOGD_PLATFORM,
- "ethtool[%d]: %s: retrieved kernel features",
- ifindex,
- "get-features");
- return features;
-}
-
-static const char *
-_ethtool_feature_state_to_string(char * buf,
- gsize buf_size,
- const NMEthtoolFeatureState *s,
- const char * prefix)
-{
- int l;
-
- l = g_snprintf(buf,
- buf_size,
- "%s %s%s",
- prefix ?: "",
- ONOFF(s->active),
- (!s->available || s->never_changed)
- ? ", [fixed]"
- : ((s->requested != s->active)
- ? (s->requested ? ", [requested on]" : ", [requested off]")
- : ""));
- nm_assert(l < buf_size);
- return buf;
-}
-
-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 */)
-{
- nm_auto_socket_handle SocketHandle shandle = SOCKET_HANDLE_INIT(ifindex);
- gs_free struct ethtool_sfeatures * sfeatures_free = NULL;
- struct ethtool_sfeatures * sfeatures;
- gsize sfeatures_len;
- int r;
- guint i, j;
- struct {
- const NMEthtoolFeatureState *f_state;
- NMOptionBool requested;
- } set_states[N_ETHTOOL_KERNEL_FEATURES];
- guint set_states_n = 0;
- gboolean success = TRUE;
-
- g_return_val_if_fail(ifindex > 0, 0);
- g_return_val_if_fail(features, 0);
- g_return_val_if_fail(requested, 0);
-
- nm_assert(features->n_states <= N_ETHTOOL_KERNEL_FEATURES);
-
- for (i = 0; i < _NM_ETHTOOL_ID_FEATURE_NUM; i++) {
- const NMEthtoolFeatureState *const *states_indexed;
-
- if (requested[i] == NM_OPTION_BOOL_DEFAULT)
- continue;
-
- if (!(states_indexed = features->states_indexed[i])) {
- if (do_set) {
- nm_log_trace(LOGD_PLATFORM,
- "ethtool[%d]: %s: set feature %s: skip (not found)",
- ifindex,
- "set-features",
- nm_ethtool_data[i + _NM_ETHTOOL_ID_FEATURE_FIRST]->optname);
- success = FALSE;
- }
- continue;
- }
-
- for (j = 0; states_indexed[j]; j++) {
- const NMEthtoolFeatureState *s = states_indexed[j];
- char sbuf[255];
-
- if (set_states_n >= G_N_ELEMENTS(set_states))
- g_return_val_if_reached(FALSE);
-
- if (s->never_changed) {
- nm_log_trace(LOGD_PLATFORM,
- "ethtool[%d]: %s: %s feature %s (%s): %s, %s (skip feature marked as "
- "never changed)",
- ifindex,
- "set-features",
- do_set ? "set" : "reset",
- nm_ethtool_data[i + _NM_ETHTOOL_ID_FEATURE_FIRST]->optname,
- s->info->kernel_names[s->idx_kernel_name],
- ONOFF(do_set ? requested[i] == NM_OPTION_BOOL_TRUE : s->active),
- _ethtool_feature_state_to_string(sbuf,
- sizeof(sbuf),
- s,
- do_set ? " currently:" : " before:"));
- continue;
- }
-
- nm_log_trace(LOGD_PLATFORM,
- "ethtool[%d]: %s: %s feature %s (%s): %s, %s",
- ifindex,
- "set-features",
- do_set ? "set" : "reset",
- nm_ethtool_data[i + _NM_ETHTOOL_ID_FEATURE_FIRST]->optname,
- s->info->kernel_names[s->idx_kernel_name],
- ONOFF(do_set ? requested[i] == NM_OPTION_BOOL_TRUE : s->active),
- _ethtool_feature_state_to_string(sbuf,
- sizeof(sbuf),
- s,
- do_set ? " currently:" : " before:"));
-
- if (do_set && (!s->available || s->never_changed)
- && (s->active != (requested[i] == NM_OPTION_BOOL_TRUE))) {
- /* we request to change a flag which kernel reported as fixed.
- * While the ethtool operation will silently succeed, mark the request
- * as failure. */
- success = FALSE;
- }
-
- set_states[set_states_n].f_state = s;
- set_states[set_states_n].requested = requested[i];
- set_states_n++;
- }
- }
-
- if (set_states_n == 0) {
- nm_log_trace(LOGD_PLATFORM,
- "ethtool[%d]: %s: no feature requested",
- ifindex,
- "set-features");
- return TRUE;
- }
-
- sfeatures_len =
- sizeof(struct ethtool_sfeatures)
- + (NM_DIV_ROUND_UP(features->n_ss_features, 32U) * sizeof(sfeatures->features[0]));
- sfeatures = nm_malloc0_maybe_a(300, sfeatures_len, &sfeatures_free);
- sfeatures->cmd = ETHTOOL_SFEATURES;
- sfeatures->size = NM_DIV_ROUND_UP(features->n_ss_features, 32U);
-
- for (i = 0; i < set_states_n; i++) {
- const NMEthtoolFeatureState *s = set_states[i].f_state;
- guint i_block;
- guint32 i_flag;
- gboolean is_requested;
-
- i_block = s->idx_ss_features / 32u;
- i_flag = (guint32)(1u << (s->idx_ss_features % 32u));
-
- sfeatures->features[i_block].valid |= i_flag;
-
- if (do_set)
- is_requested = (set_states[i].requested == NM_OPTION_BOOL_TRUE);
- else
- is_requested = s->active;
-
- if (is_requested)
- sfeatures->features[i_block].requested |= i_flag;
- else
- sfeatures->features[i_block].requested &= ~i_flag;
- }
-
- r = _ethtool_call_handle(&shandle, sfeatures, sfeatures_len);
- if (r < 0) {
- success = FALSE;
- nm_log_trace(LOGD_PLATFORM,
- "ethtool[%d]: %s: failure setting features (%s)",
- ifindex,
- "set-features",
- nm_strerror_native(-r));
- return FALSE;
- }
-
- nm_log_trace(LOGD_PLATFORM,
- "ethtool[%d]: %s: %s",
- ifindex,
- "set-features",
- success ? "successfully setting features"
- : "at least some of the features were not successfully set");
- return success;
-}
-
-static gboolean
-ethtool_get_coalesce(SocketHandle *shandle, NMEthtoolCoalesceState *coalesce)
-{
- struct ethtool_coalesce eth_data;
-
- eth_data.cmd = ETHTOOL_GCOALESCE;
-
- if (_ethtool_call_handle(shandle, &eth_data, sizeof(struct ethtool_coalesce)) != 0)
- return FALSE;
-
- *coalesce = (NMEthtoolCoalesceState){
- .s = {
- [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_RX_USECS)] =
- eth_data.rx_coalesce_usecs,
- [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_RX_FRAMES)] =
- eth_data.rx_max_coalesced_frames,
- [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_RX_USECS_IRQ)] =
- eth_data.rx_coalesce_usecs_irq,
- [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_RX_FRAMES_IRQ)] =
- eth_data.rx_max_coalesced_frames_irq,
- [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_TX_USECS)] =
- eth_data.tx_coalesce_usecs,
- [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_TX_FRAMES)] =
- eth_data.tx_max_coalesced_frames,
- [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_TX_USECS_IRQ)] =
- eth_data.tx_coalesce_usecs_irq,
- [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_TX_FRAMES_IRQ)] =
- eth_data.tx_max_coalesced_frames_irq,
- [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_STATS_BLOCK_USECS)] =
- eth_data.stats_block_coalesce_usecs,
- [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_ADAPTIVE_RX)] =
- eth_data.use_adaptive_rx_coalesce,
- [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_ADAPTIVE_TX)] =
- eth_data.use_adaptive_tx_coalesce,
- [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_PKT_RATE_LOW)] =
- eth_data.pkt_rate_low,
- [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_RX_USECS_LOW)] =
- eth_data.rx_coalesce_usecs_low,
- [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_RX_FRAMES_LOW)] =
- eth_data.rx_max_coalesced_frames_low,
- [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_TX_USECS_LOW)] =
- eth_data.tx_coalesce_usecs_low,
- [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_TX_FRAMES_LOW)] =
- eth_data.tx_max_coalesced_frames_low,
- [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_PKT_RATE_HIGH)] =
- eth_data.pkt_rate_high,
- [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_RX_USECS_HIGH)] =
- eth_data.rx_coalesce_usecs_high,
- [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_RX_FRAMES_HIGH)] =
- eth_data.rx_max_coalesced_frames_high,
- [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_TX_USECS_HIGH)] =
- eth_data.tx_coalesce_usecs_high,
- [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_TX_FRAMES_HIGH)] =
- eth_data.tx_max_coalesced_frames_high,
- [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_SAMPLE_INTERVAL)] =
- eth_data.rate_sample_interval,
- }};
- return TRUE;
-}
-
-gboolean
-nmp_utils_ethtool_get_coalesce(int ifindex, NMEthtoolCoalesceState *coalesce)
-{
- nm_auto_socket_handle SocketHandle shandle = SOCKET_HANDLE_INIT(ifindex);
-
- g_return_val_if_fail(ifindex > 0, FALSE);
- g_return_val_if_fail(coalesce, FALSE);
-
- if (!ethtool_get_coalesce(&shandle, coalesce)) {
- nm_log_trace(LOGD_PLATFORM,
- "ethtool[%d]: %s: failure getting coalesce settings",
- ifindex,
- "get-coalesce");
- return FALSE;
- }
-
- nm_log_trace(LOGD_PLATFORM,
- "ethtool[%d]: %s: retrieved kernel coalesce settings",
- ifindex,
- "get-coalesce");
- return TRUE;
-}
-
-static gboolean
-ethtool_set_coalesce(SocketHandle *shandle, const NMEthtoolCoalesceState *coalesce)
-{
- struct ethtool_coalesce eth_data;
- gboolean success;
-
- nm_assert(shandle);
- nm_assert(coalesce);
-
- eth_data = (struct ethtool_coalesce){
- .cmd = ETHTOOL_SCOALESCE,
- .rx_coalesce_usecs =
- coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_RX_USECS)],
- .rx_max_coalesced_frames =
- coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_RX_FRAMES)],
- .rx_coalesce_usecs_irq =
- coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_RX_USECS_IRQ)],
- .rx_max_coalesced_frames_irq =
- coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_RX_FRAMES_IRQ)],
- .tx_coalesce_usecs =
- coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_TX_USECS)],
- .tx_max_coalesced_frames =
- coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_TX_FRAMES)],
- .tx_coalesce_usecs_irq =
- coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_TX_USECS_IRQ)],
- .tx_max_coalesced_frames_irq =
- coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_TX_FRAMES_IRQ)],
- .stats_block_coalesce_usecs =
- coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_STATS_BLOCK_USECS)],
- .use_adaptive_rx_coalesce =
- coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_ADAPTIVE_RX)],
- .use_adaptive_tx_coalesce =
- coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_ADAPTIVE_TX)],
- .pkt_rate_low =
- coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_PKT_RATE_LOW)],
- .rx_coalesce_usecs_low =
- coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_RX_USECS_LOW)],
- .rx_max_coalesced_frames_low =
- coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_RX_FRAMES_LOW)],
- .tx_coalesce_usecs_low =
- coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_TX_USECS_LOW)],
- .tx_max_coalesced_frames_low =
- coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_TX_FRAMES_LOW)],
- .pkt_rate_high =
- coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_PKT_RATE_HIGH)],
- .rx_coalesce_usecs_high =
- coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_RX_USECS_HIGH)],
- .rx_max_coalesced_frames_high =
- coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_RX_FRAMES_HIGH)],
- .tx_coalesce_usecs_high =
- coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_TX_USECS_HIGH)],
- .tx_max_coalesced_frames_high =
- coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_TX_FRAMES_HIGH)],
- .rate_sample_interval =
- coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_SAMPLE_INTERVAL)],
- };
-
- success = (_ethtool_call_handle(shandle, &eth_data, sizeof(struct ethtool_coalesce)) == 0);
- return success;
-}
-
-gboolean
-nmp_utils_ethtool_set_coalesce(int ifindex, const NMEthtoolCoalesceState *coalesce)
-{
- nm_auto_socket_handle SocketHandle shandle = SOCKET_HANDLE_INIT(ifindex);
-
- g_return_val_if_fail(ifindex > 0, FALSE);
- g_return_val_if_fail(coalesce, FALSE);
-
- if (!ethtool_set_coalesce(&shandle, coalesce)) {
- nm_log_trace(LOGD_PLATFORM,
- "ethtool[%d]: %s: failure setting coalesce settings",
- ifindex,
- "set-coalesce");
- return FALSE;
- }
-
- nm_log_trace(LOGD_PLATFORM,
- "ethtool[%d]: %s: set kernel coalesce settings",
- ifindex,
- "set-coalesce");
- return TRUE;
-}
-
-static gboolean
-ethtool_get_ring(SocketHandle *shandle, NMEthtoolRingState *ring)
-{
- struct ethtool_ringparam eth_data;
-
- eth_data.cmd = ETHTOOL_GRINGPARAM;
-
- if (_ethtool_call_handle(shandle, &eth_data, sizeof(struct ethtool_ringparam)) != 0)
- return FALSE;
-
- ring->rx_pending = eth_data.rx_pending;
- ring->rx_jumbo_pending = eth_data.rx_jumbo_pending;
- ring->rx_mini_pending = eth_data.rx_mini_pending;
- ring->tx_pending = eth_data.tx_pending;
-
- return TRUE;
-}
-
-gboolean
-nmp_utils_ethtool_get_ring(int ifindex, NMEthtoolRingState *ring)
-{
- nm_auto_socket_handle SocketHandle shandle = SOCKET_HANDLE_INIT(ifindex);
-
- g_return_val_if_fail(ifindex > 0, FALSE);
- g_return_val_if_fail(ring, FALSE);
-
- if (!ethtool_get_ring(&shandle, ring)) {
- nm_log_trace(LOGD_PLATFORM,
- "ethtool[%d]: %s: failure getting ring settings",
- ifindex,
- "get-ring");
- return FALSE;
- }
-
- nm_log_trace(LOGD_PLATFORM,
- "ethtool[%d]: %s: retrieved kernel ring settings",
- ifindex,
- "get-ring");
- return TRUE;
-}
-
-static gboolean
-ethtool_set_ring(SocketHandle *shandle, const NMEthtoolRingState *ring)
-{
- gboolean success;
- struct ethtool_ringparam eth_data;
-
- g_return_val_if_fail(shandle, 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,
- };
-
- success = (_ethtool_call_handle(shandle, &eth_data, sizeof(struct ethtool_ringparam)) == 0);
- return success;
-}
-
-gboolean
-nmp_utils_ethtool_set_ring(int ifindex, const NMEthtoolRingState *ring)
-{
- nm_auto_socket_handle SocketHandle shandle = SOCKET_HANDLE_INIT(ifindex);
-
- g_return_val_if_fail(ifindex > 0, FALSE);
- g_return_val_if_fail(ring, FALSE);
-
- if (!ethtool_set_ring(&shandle, ring)) {
- 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_utils_ethtool_get_driver_info(int ifindex, NMPUtilsEthtoolDriverInfo *data)
-{
- struct ethtool_drvinfo *drvinfo;
-
- G_STATIC_ASSERT_EXPR(sizeof(*data) == sizeof(*drvinfo));
- G_STATIC_ASSERT_EXPR(offsetof(NMPUtilsEthtoolDriverInfo, driver)
- == offsetof(struct ethtool_drvinfo, driver));
- G_STATIC_ASSERT_EXPR(offsetof(NMPUtilsEthtoolDriverInfo, version)
- == offsetof(struct ethtool_drvinfo, version));
- G_STATIC_ASSERT_EXPR(offsetof(NMPUtilsEthtoolDriverInfo, fw_version)
- == offsetof(struct ethtool_drvinfo, fw_version));
- G_STATIC_ASSERT_EXPR(sizeof(data->driver) == sizeof(drvinfo->driver));
- G_STATIC_ASSERT_EXPR(sizeof(data->version) == sizeof(drvinfo->version));
- G_STATIC_ASSERT_EXPR(sizeof(data->fw_version) == sizeof(drvinfo->fw_version));
-
- g_return_val_if_fail(ifindex > 0, FALSE);
- g_return_val_if_fail(data, FALSE);
-
- drvinfo = (struct ethtool_drvinfo *) data;
- *drvinfo = (struct ethtool_drvinfo){
- .cmd = ETHTOOL_GDRVINFO,
- };
- return _ethtool_call_once(ifindex, drvinfo, sizeof(*drvinfo)) >= 0;
-}
-
-gboolean
-nmp_utils_ethtool_get_permanent_address(int ifindex, guint8 *buf, size_t *length)
-{
- struct {
- struct ethtool_perm_addr e;
- guint8 _extra_data[_NM_UTILS_HWADDR_LEN_MAX + 1];
- } edata = {
- .e.cmd = ETHTOOL_GPERMADDR,
- .e.size = _NM_UTILS_HWADDR_LEN_MAX,
- };
- const guint8 *pdata;
-
- guint i;
-
- g_return_val_if_fail(ifindex > 0, FALSE);
-
- if (_ethtool_call_once(ifindex, &edata, sizeof(edata)) < 0)
- return FALSE;
-
- if (edata.e.size > _NM_UTILS_HWADDR_LEN_MAX)
- return FALSE;
- if (edata.e.size < 1)
- return FALSE;
-
- pdata = (const guint8 *) edata.e.data;
-
- if (NM_IN_SET(pdata[0], 0, 0xFF)) {
- /* Some drivers might return a permanent address of all zeros.
- * Reject that (rh#1264024)
- *
- * Some drivers return a permanent address of all ones. Reject that too */
- for (i = 1; i < edata.e.size; i++) {
- if (pdata[0] != pdata[i])
- goto not_all_0or1;
- }
- return FALSE;
- }
-
-not_all_0or1:
- memcpy(buf, pdata, edata.e.size);
- *length = edata.e.size;
- return TRUE;
-}
-
-gboolean
-nmp_utils_ethtool_supports_carrier_detect(int ifindex)
-{
- struct ethtool_cmd edata = {.cmd = ETHTOOL_GLINK};
-
- g_return_val_if_fail(ifindex > 0, FALSE);
-
- /* We ignore the result. If the ETHTOOL_GLINK call succeeded, then we
- * assume the device supports carrier-detect, otherwise we assume it
- * doesn't.
- */
- return _ethtool_call_once(ifindex, &edata, sizeof(edata)) >= 0;
-}
-
-gboolean
-nmp_utils_ethtool_supports_vlans(int ifindex)
-{
- nm_auto_socket_handle SocketHandle shandle = SOCKET_HANDLE_INIT(ifindex);
- gs_free struct ethtool_gfeatures * features_free = NULL;
- struct ethtool_gfeatures * features;
- gsize features_len;
- int idx, block, bit, size;
-
- g_return_val_if_fail(ifindex > 0, FALSE);
-
- idx = ethtool_get_stringset_index(&shandle, ETH_SS_FEATURES, "vlan-challenged");
- if (idx < 0) {
- nm_log_dbg(LOGD_PLATFORM,
- "ethtool[%d]: vlan-challenged ethtool feature does not exist?",
- ifindex);
- return FALSE;
- }
-
- block = idx / 32;
- bit = idx % 32;
- size = block + 1;
-
- features_len = sizeof(*features) + (size * sizeof(struct ethtool_get_features_block));
- features = nm_malloc0_maybe_a(300, features_len, &features_free);
- features->cmd = ETHTOOL_GFEATURES;
- features->size = size;
-
- if (_ethtool_call_handle(&shandle, features, features_len) < 0)
- return FALSE;
-
- return !(features->features[block].active & (1 << bit));
-}
-
-int
-nmp_utils_ethtool_get_peer_ifindex(int ifindex)
-{
- nm_auto_socket_handle SocketHandle shandle = SOCKET_HANDLE_INIT(ifindex);
- gsize stats_len;
- gs_free struct ethtool_stats * stats_free = NULL;
- struct ethtool_stats * stats;
- int peer_ifindex_stat;
-
- g_return_val_if_fail(ifindex > 0, 0);
-
- peer_ifindex_stat = ethtool_get_stringset_index(&shandle, ETH_SS_STATS, "peer_ifindex");
- if (peer_ifindex_stat < 0) {
- nm_log_dbg(LOGD_PLATFORM, "ethtool[%d]: peer_ifindex stat does not exist?", ifindex);
- return FALSE;
- }
-
- stats_len = sizeof(*stats) + (peer_ifindex_stat + 1) * sizeof(guint64);
- stats = nm_malloc0_maybe_a(300, stats_len, &stats_free);
- stats->cmd = ETHTOOL_GSTATS;
- stats->n_stats = peer_ifindex_stat + 1;
- if (_ethtool_call_handle(&shandle, stats, stats_len) < 0)
- return 0;
-
- return stats->data[peer_ifindex_stat];
-}
-
-gboolean
-nmp_utils_ethtool_get_wake_on_lan(int ifindex)
-{
- struct ethtool_wolinfo wol = {
- .cmd = ETHTOOL_GWOL,
- };
-
- g_return_val_if_fail(ifindex > 0, FALSE);
-
- if (_ethtool_call_once(ifindex, &wol, sizeof(wol)) < 0)
- return FALSE;
-
- return wol.wolopts != 0;
-}
-
-gboolean
-nmp_utils_ethtool_get_link_settings(int ifindex,
- gboolean * out_autoneg,
- guint32 * out_speed,
- NMPlatformLinkDuplexType *out_duplex)
-{
- struct ethtool_cmd edata = {
- .cmd = ETHTOOL_GSET,
- };
-
- g_return_val_if_fail(ifindex > 0, FALSE);
-
- if (_ethtool_call_once(ifindex, &edata, sizeof(edata)) < 0)
- return FALSE;
-
- NM_SET_OUT(out_autoneg, (edata.autoneg == AUTONEG_ENABLE));
-
- if (out_speed) {
- guint32 speed;
-
- speed = ethtool_cmd_speed(&edata);
- if (speed == G_MAXUINT16 || speed == G_MAXUINT32)
- speed = 0;
-
- *out_speed = speed;
- }
-
- if (out_duplex) {
- switch (edata.duplex) {
- case DUPLEX_HALF:
- *out_duplex = NM_PLATFORM_LINK_DUPLEX_HALF;
- break;
- case DUPLEX_FULL:
- *out_duplex = NM_PLATFORM_LINK_DUPLEX_FULL;
- break;
- default: /* DUPLEX_UNKNOWN */
- *out_duplex = NM_PLATFORM_LINK_DUPLEX_UNKNOWN;
- break;
- }
- }
-
- return TRUE;
-}
-
-#define ADVERTISED_INVALID 0
-#define BASET_ALL_MODES \
- (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | ADVERTISED_100baseT_Half \
- | ADVERTISED_100baseT_Full | ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full \
- | ADVERTISED_10000baseT_Full)
-
-static guint32
-get_baset_mode(guint32 speed, NMPlatformLinkDuplexType duplex)
-{
- if (duplex == NM_PLATFORM_LINK_DUPLEX_UNKNOWN)
- return ADVERTISED_INVALID;
-
- if (duplex == NM_PLATFORM_LINK_DUPLEX_HALF) {
- switch (speed) {
- case 10:
- return ADVERTISED_10baseT_Half;
- case 100:
- return ADVERTISED_100baseT_Half;
- case 1000:
- return ADVERTISED_1000baseT_Half;
- default:
- return ADVERTISED_INVALID;
- }
- } else {
- switch (speed) {
- case 10:
- return ADVERTISED_10baseT_Full;
- case 100:
- return ADVERTISED_100baseT_Full;
- case 1000:
- return ADVERTISED_1000baseT_Full;
- case 10000:
- return ADVERTISED_10000baseT_Full;
- default:
- return ADVERTISED_INVALID;
- }
- }
-}
-
-gboolean
-nmp_utils_ethtool_set_link_settings(int ifindex,
- gboolean autoneg,
- guint32 speed,
- NMPlatformLinkDuplexType duplex)
-{
- nm_auto_socket_handle SocketHandle shandle = SOCKET_HANDLE_INIT(ifindex);
- struct ethtool_cmd edata = {
- .cmd = ETHTOOL_GSET,
- };
-
- g_return_val_if_fail(ifindex > 0, FALSE);
- g_return_val_if_fail((speed && duplex != NM_PLATFORM_LINK_DUPLEX_UNKNOWN)
- || (!speed && duplex == NM_PLATFORM_LINK_DUPLEX_UNKNOWN),
- FALSE);
-
- /* retrieve first current settings */
- if (_ethtool_call_handle(&shandle, &edata, sizeof(edata)) < 0)
- return FALSE;
-
- /* FIXME: try first new ETHTOOL_GLINKSETTINGS/SLINKSETTINGS API
- * https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=3f1ac7a700d039c61d8d8b99f28d605d489a60cf
- */
-
- /* then change the needed ones */
- edata.cmd = ETHTOOL_SSET;
- if (autoneg) {
- edata.autoneg = AUTONEG_ENABLE;
- if (!speed)
- edata.advertising = edata.supported;
- else {
- guint32 mode;
-
- mode = get_baset_mode(speed, duplex);
-
- if (!mode) {
- nm_log_trace(LOGD_PLATFORM,
- "ethtool[%d]: %uBASE-T %s duplex mode cannot be advertised",
- ifindex,
- speed,
- nm_platform_link_duplex_type_to_string(duplex));
- return FALSE;
- }
- if (!(edata.supported & mode)) {
- nm_log_trace(LOGD_PLATFORM,
- "ethtool[%d]: device does not support %uBASE-T %s duplex mode",
- ifindex,
- speed,
- nm_platform_link_duplex_type_to_string(duplex));
- return FALSE;
- }
- edata.advertising = (edata.supported & ~BASET_ALL_MODES) | mode;
- }
- } else {
- edata.autoneg = AUTONEG_DISABLE;
-
- if (speed)
- ethtool_cmd_speed_set(&edata, speed);
-
- switch (duplex) {
- case NM_PLATFORM_LINK_DUPLEX_HALF:
- edata.duplex = DUPLEX_HALF;
- break;
- case NM_PLATFORM_LINK_DUPLEX_FULL:
- edata.duplex = DUPLEX_FULL;
- break;
- case NM_PLATFORM_LINK_DUPLEX_UNKNOWN:
- break;
- default:
- g_return_val_if_reached(FALSE);
- }
- }
-
- return _ethtool_call_handle(&shandle, &edata, sizeof(edata)) >= 0;
-}
-
-gboolean
-nmp_utils_ethtool_set_wake_on_lan(int ifindex,
- _NMSettingWiredWakeOnLan wol,
- const char * wol_password)
-{
- struct ethtool_wolinfo wol_info = {
- .cmd = ETHTOOL_SWOL,
- .wolopts = 0,
- };
-
- g_return_val_if_fail(ifindex > 0, FALSE);
-
- if (wol == _NM_SETTING_WIRED_WAKE_ON_LAN_IGNORE)
- return TRUE;
-
- nm_log_dbg(LOGD_PLATFORM,
- "ethtool[%d]: setting Wake-on-LAN options 0x%x, password '%s'",
- ifindex,
- (unsigned) wol,
- wol_password);
-
- if (NM_FLAGS_HAS(wol, _NM_SETTING_WIRED_WAKE_ON_LAN_PHY))
- wol_info.wolopts |= WAKE_PHY;
- if (NM_FLAGS_HAS(wol, _NM_SETTING_WIRED_WAKE_ON_LAN_UNICAST))
- wol_info.wolopts |= WAKE_UCAST;
- if (NM_FLAGS_HAS(wol, _NM_SETTING_WIRED_WAKE_ON_LAN_MULTICAST))
- wol_info.wolopts |= WAKE_MCAST;
- if (NM_FLAGS_HAS(wol, _NM_SETTING_WIRED_WAKE_ON_LAN_BROADCAST))
- wol_info.wolopts |= WAKE_BCAST;
- if (NM_FLAGS_HAS(wol, _NM_SETTING_WIRED_WAKE_ON_LAN_ARP))
- wol_info.wolopts |= WAKE_ARP;
- if (NM_FLAGS_HAS(wol, _NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC))
- wol_info.wolopts |= WAKE_MAGIC;
-
- if (wol_password) {
- if (!_nm_utils_hwaddr_aton_exact(wol_password, wol_info.sopass, ETH_ALEN)) {
- nm_log_dbg(LOGD_PLATFORM,
- "ethtool[%d]: couldn't parse Wake-on-LAN password '%s'",
- ifindex,
- wol_password);
- return FALSE;
- }
- wol_info.wolopts |= WAKE_MAGICSECURE;
- }
-
- return _ethtool_call_once(ifindex, &wol_info, sizeof(wol_info)) >= 0;
-}
-
-/******************************************************************************
- * mii
- *****************************************************************************/
-
-gboolean
-nmp_utils_mii_supports_carrier_detect(int ifindex)
-{
- nm_auto_socket_handle SocketHandle shandle = SOCKET_HANDLE_INIT(ifindex);
- int r;
- struct ifreq ifr;
- struct mii_ioctl_data * mii;
-
- g_return_val_if_fail(ifindex > 0, FALSE);
-
- r = _ioctl_call("mii",
- "SIOCGMIIPHY",
- SIOCGMIIPHY,
- shandle.ifindex,
- &shandle.fd,
- shandle.ifname,
- IOCTL_CALL_DATA_TYPE_NONE,
- NULL,
- 0,
- &ifr);
- if (r < 0)
- return FALSE;
-
- /* If we can read the BMSR register, we assume that the card supports MII link detection */
- mii = (struct mii_ioctl_data *) &ifr.ifr_ifru;
- mii->reg_num = MII_BMSR;
-
- r = _ioctl_call("mii",
- "SIOCGMIIREG",
- SIOCGMIIREG,
- shandle.ifindex,
- &shandle.fd,
- shandle.ifname,
- IOCTL_CALL_DATA_TYPE_IFRU,
- mii,
- sizeof(*mii),
- &ifr);
- if (r < 0)
- return FALSE;
-
- mii = (struct mii_ioctl_data *) &ifr.ifr_ifru;
- nm_log_trace(LOGD_PLATFORM,
- "mii[%d,%s]: carrier-detect yes: SIOCGMIIREG result 0x%X",
- ifindex,
- shandle.ifname,
- mii->val_out);
- return TRUE;
-}
-
-/******************************************************************************
- * udev
- *****************************************************************************/
-
-const char *
-nmp_utils_udev_get_driver(struct udev_device *udevice)
-{
- struct udev_device *parent = NULL, *grandparent = NULL;
- const char * driver, *subsys;
-
- driver = udev_device_get_driver(udevice);
- if (driver)
- goto out;
-
- /* Try the parent */
- parent = udev_device_get_parent(udevice);
- if (parent) {
- driver = udev_device_get_driver(parent);
- if (!driver) {
- /* Try the grandparent if it's an ibmebus device or if the
- * subsys is NULL which usually indicates some sort of
- * platform device like a 'gadget' net interface.
- */
- subsys = udev_device_get_subsystem(parent);
- if ((g_strcmp0(subsys, "ibmebus") == 0) || (subsys == NULL)) {
- grandparent = udev_device_get_parent(parent);
- if (grandparent)
- driver = udev_device_get_driver(grandparent);
- }
- }
- }
-
-out:
- /* Intern the string so we don't have to worry about memory
- * management in NMPlatformLink. */
- return g_intern_string(driver);
-}
-
-/******************************************************************************
- * utils
- *****************************************************************************/
-
-NMIPConfigSource
-nmp_utils_ip_config_source_from_rtprot(guint8 rtprot)
-{
- return ((int) rtprot) + 1;
-}
-
-NMIPConfigSource
-nmp_utils_ip_config_source_round_trip_rtprot(NMIPConfigSource source)
-{
- /* when adding a route to kernel for a give @source, the resulting route
- * will be put into the cache with a source of NM_IP_CONFIG_SOURCE_RTPROT_*.
- * This function returns that. */
- return nmp_utils_ip_config_source_from_rtprot(
- nmp_utils_ip_config_source_coerce_to_rtprot(source));
-}
-
-guint8
-nmp_utils_ip_config_source_coerce_to_rtprot(NMIPConfigSource source)
-{
- /* when adding a route to kernel, we coerce the @source field
- * to rtm_protocol. This is not lossless as we map different
- * source values to the same RTPROT uint8 value. */
- if (source <= NM_IP_CONFIG_SOURCE_UNKNOWN)
- return RTPROT_UNSPEC;
-
- if (source <= _NM_IP_CONFIG_SOURCE_RTPROT_LAST)
- return source - 1;
-
- switch (source) {
- case NM_IP_CONFIG_SOURCE_KERNEL:
- return RTPROT_KERNEL;
- case NM_IP_CONFIG_SOURCE_IP6LL:
- return RTPROT_KERNEL;
- case NM_IP_CONFIG_SOURCE_DHCP:
- return RTPROT_DHCP;
- case NM_IP_CONFIG_SOURCE_NDISC:
- return RTPROT_RA;
-
- default:
- return RTPROT_STATIC;
- }
-}
-
-NMIPConfigSource
-nmp_utils_ip_config_source_coerce_from_rtprot(NMIPConfigSource source)
-{
- /* When we receive a route from kernel and put it into the platform cache,
- * we preserve the protocol field by converting it to a NMIPConfigSource
- * via nmp_utils_ip_config_source_from_rtprot().
- *
- * However, that is not the inverse of nmp_utils_ip_config_source_coerce_to_rtprot().
- * Instead, to go back to the original value, you need another step:
- * nmp_utils_ip_config_source_coerce_from_rtprot (nmp_utils_ip_config_source_from_rtprot (rtprot)).
- *
- * This might partly restore the original source value, but of course that
- * is not really possible because nmp_utils_ip_config_source_coerce_to_rtprot()
- * is not injective.
- * */
- switch (source) {
- case NM_IP_CONFIG_SOURCE_RTPROT_UNSPEC:
- return NM_IP_CONFIG_SOURCE_UNKNOWN;
-
- case NM_IP_CONFIG_SOURCE_RTPROT_KERNEL:
- case NM_IP_CONFIG_SOURCE_RTPROT_REDIRECT:
- return NM_IP_CONFIG_SOURCE_KERNEL;
-
- case NM_IP_CONFIG_SOURCE_RTPROT_RA:
- return NM_IP_CONFIG_SOURCE_NDISC;
-
- case NM_IP_CONFIG_SOURCE_RTPROT_DHCP:
- return NM_IP_CONFIG_SOURCE_DHCP;
-
- default:
- return NM_IP_CONFIG_SOURCE_USER;
- }
-}
-
-const char *
-nmp_utils_ip_config_source_to_string(NMIPConfigSource source, char *buf, gsize len)
-{
- const char *s = NULL;
- nm_utils_to_string_buffer_init(&buf, &len);
-
- if (!len)
- return buf;
-
- switch (source) {
- case NM_IP_CONFIG_SOURCE_UNKNOWN:
- s = "unknown";
- break;
-
- case NM_IP_CONFIG_SOURCE_RTPROT_UNSPEC:
- s = "rt-unspec";
- break;
- case NM_IP_CONFIG_SOURCE_RTPROT_REDIRECT:
- s = "rt-redirect";
- break;
- case NM_IP_CONFIG_SOURCE_RTPROT_KERNEL:
- s = "rt-kernel";
- break;
- case NM_IP_CONFIG_SOURCE_RTPROT_BOOT:
- s = "rt-boot";
- break;
- case NM_IP_CONFIG_SOURCE_RTPROT_STATIC:
- s = "rt-static";
- break;
- case NM_IP_CONFIG_SOURCE_RTPROT_DHCP:
- s = "rt-dhcp";
- break;
- case NM_IP_CONFIG_SOURCE_RTPROT_RA:
- s = "rt-ra";
- break;
-
- case NM_IP_CONFIG_SOURCE_KERNEL:
- s = "kernel";
- break;
- case NM_IP_CONFIG_SOURCE_SHARED:
- s = "shared";
- break;
- case NM_IP_CONFIG_SOURCE_IP4LL:
- s = "ipv4ll";
- break;
- case NM_IP_CONFIG_SOURCE_IP6LL:
- s = "ipv6ll";
- break;
- case NM_IP_CONFIG_SOURCE_PPP:
- s = "ppp";
- break;
- case NM_IP_CONFIG_SOURCE_WWAN:
- s = "wwan";
- break;
- case NM_IP_CONFIG_SOURCE_VPN:
- s = "vpn";
- break;
- case NM_IP_CONFIG_SOURCE_DHCP:
- s = "dhcp";
- break;
- case NM_IP_CONFIG_SOURCE_NDISC:
- s = "ndisc";
- break;
- case NM_IP_CONFIG_SOURCE_USER:
- s = "user";
- break;
- default:
- break;
- }
-
- if (source >= 1 && source <= 0x100) {
- if (s)
- g_snprintf(buf, len, "%s", s);
- else
- g_snprintf(buf, len, "rt-%d", ((int) source) - 1);
- } else {
- if (s)
- g_strlcpy(buf, s, len);
- else
- g_snprintf(buf, len, "(%d)", source);
- }
- return buf;
-}
-
-/**
- * nmp_utils_sysctl_open_netdir:
- * @ifindex: the ifindex for which to open "/sys/class/net/%s"
- * @ifname_guess: (allow-none): optional argument, if present used as initial
- * guess as the current name for @ifindex. If guessed right,
- * it saves an additional if_indextoname() call.
- * @out_ifname: (allow-none): if present, must be at least IFNAMSIZ
- * characters. On success, this will contain the actual ifname
- * found while opening the directory.
- *
- * Returns: a negative value on failure, on success returns the open fd
- * to the "/sys/class/net/%s" directory for @ifindex.
- */
-int
-nmp_utils_sysctl_open_netdir(int ifindex, const char *ifname_guess, char *out_ifname)
-{
-#define SYS_CLASS_NET "/sys/class/net/"
- const char *ifname = ifname_guess;
- char ifname_buf_last_try[IFNAMSIZ];
- char ifname_buf[IFNAMSIZ];
- guint try_count = 0;
- char sysdir[NM_STRLEN(SYS_CLASS_NET) + IFNAMSIZ] = SYS_CLASS_NET;
- char fd_buf[256];
- ssize_t nn;
-
- g_return_val_if_fail(ifindex >= 0, -1);
-
- ifname_buf_last_try[0] = '\0';
-
- for (try_count = 0; try_count < 10; try_count++, ifname = NULL) {
- nm_auto_close int fd_dir = -1;
- nm_auto_close int fd_ifindex = -1;
-
- if (!ifname) {
- ifname = nmp_utils_if_indextoname(ifindex, ifname_buf);
- if (!ifname)
- return -1;
- }
-
- nm_assert(nm_utils_ifname_valid_kernel(ifname, NULL));
-
- if (g_strlcpy(&sysdir[NM_STRLEN(SYS_CLASS_NET)], ifname, IFNAMSIZ) >= IFNAMSIZ)
- g_return_val_if_reached(-1);
-
- /* we only retry, if the name changed since previous attempt.
- * Hence, it is extremely unlikely that this loop runes until the
- * end of the @try_count. */
- if (nm_streq(ifname, ifname_buf_last_try))
- return -1;
- strcpy(ifname_buf_last_try, ifname);
-
- fd_dir = open(sysdir, O_DIRECTORY | O_CLOEXEC);
- if (fd_dir < 0)
- continue;
-
- fd_ifindex = openat(fd_dir, "ifindex", O_CLOEXEC);
- if (fd_ifindex < 0)
- continue;
-
- nn = nm_utils_fd_read_loop(fd_ifindex, fd_buf, sizeof(fd_buf) - 2, FALSE);
- if (nn <= 0)
- continue;
- fd_buf[nn] = '\0';
-
- if (ifindex != (int) _nm_utils_ascii_str_to_int64(fd_buf, 10, 1, G_MAXINT, -1))
- continue;
-
- if (out_ifname)
- strcpy(out_ifname, ifname);
-
- return nm_steal_fd(&fd_dir);
- }
-
- return -1;
-}
diff --git a/src/platform/nm-platform-utils.h b/src/platform/nm-platform-utils.h
deleted file mode 100644
index d74723eb9f..0000000000
--- a/src/platform/nm-platform-utils.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2015 Red Hat, Inc.
- */
-
-#ifndef __NM_PLATFORM_UTILS_H__
-#define __NM_PLATFORM_UTILS_H__
-
-#include "nm-base/nm-base.h"
-#include "nm-platform/nmp-base.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);
-
-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_mii_supports_carrier_detect(int ifindex);
-
-struct udev_device;
-
-const char *nmp_utils_udev_get_driver(struct udev_device *udevice);
-
-NMIPConfigSource nmp_utils_ip_config_source_from_rtprot(guint8 rtprot) _nm_const;
-guint8 nmp_utils_ip_config_source_coerce_to_rtprot(NMIPConfigSource source) _nm_const;
-NMIPConfigSource nmp_utils_ip_config_source_coerce_from_rtprot(NMIPConfigSource source) _nm_const;
-NMIPConfigSource nmp_utils_ip_config_source_round_trip_rtprot(NMIPConfigSource source) _nm_const;
-const char *nmp_utils_ip_config_source_to_string(NMIPConfigSource source, char *buf, gsize len);
-
-const char *nmp_utils_if_indextoname(int ifindex, char *out_ifname /*IFNAMSIZ*/);
-int nmp_utils_if_nametoindex(const char *ifname);
-
-int nmp_utils_sysctl_open_netdir(int ifindex, const char *ifname_guess, char *out_ifname);
-
-#endif /* __NM_PLATFORM_UTILS_H__ */
diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c
index bf2ee5d19c..6411abbacc 100644
--- a/src/platform/nm-platform.c
+++ b/src/platform/nm-platform.c
@@ -29,7 +29,7 @@
#include "nm-glib-aux/nm-secret-utils.h"
#include "nm-core-utils.h"
-#include "nm-platform-utils.h"
+#include "nm-platform/nm-platform-utils.h"
#include "nm-platform-private.h"
#include "nmp-object.h"
#include "nm-platform/nmp-netns.h"
diff --git a/src/platform/nmp-object.c b/src/platform/nmp-object.c
index 16edbd1216..9520013ad7 100644
--- a/src/platform/nmp-object.c
+++ b/src/platform/nmp-object.c
@@ -16,7 +16,7 @@
#include "nm-glib-aux/nm-secret-utils.h"
#include "nm-core-utils.h"
-#include "nm-platform-utils.h"
+#include "nm-platform/nm-platform-utils.h"
#include "wifi/nm-wifi-utils.h"
#include "wpan/nm-wpan-utils.h"
diff --git a/src/platform/tests/test-link.c b/src/platform/tests/test-link.c
index 6dc9f3e453..895b89a09b 100644
--- a/src/platform/tests/test-link.c
+++ b/src/platform/tests/test-link.c
@@ -15,7 +15,7 @@
#include "nm-base/nm-ethtool-base.h"
#include "platform/nmp-object.h"
#include "nm-platform/nmp-netns.h"
-#include "platform/nm-platform-utils.h"
+#include "nm-platform/nm-platform-utils.h"
#include "test-common.h"
#include "nm-test-utils-core.h"
diff --git a/src/platform/tests/test-platform-general.c b/src/platform/tests/test-platform-general.c
index ee99348077..00671cfba0 100644
--- a/src/platform/tests/test-platform-general.c
+++ b/src/platform/tests/test-platform-general.c
@@ -7,7 +7,7 @@
#include <linux/rtnetlink.h>
-#include "platform/nm-platform-utils.h"
+#include "nm-platform/nm-platform-utils.h"
#include "platform/nm-linux-platform.h"
#include "nm-test-utils-core.h"
diff --git a/src/platform/tests/test-route.c b/src/platform/tests/test-route.c
index f814d8c78b..0aa94ecd2d 100644
--- a/src/platform/tests/test-route.c
+++ b/src/platform/tests/test-route.c
@@ -9,7 +9,7 @@
#include <linux/fib_rules.h>
#include "nm-core-utils.h"
-#include "platform/nm-platform-utils.h"
+#include "nm-platform/nm-platform-utils.h"
#include "platform/nmp-rules-manager.h"
#include "test-common.h"
diff --git a/src/platform/tests/test-tc.c b/src/platform/tests/test-tc.c
index d178398eb8..c005b069f0 100644
--- a/src/platform/tests/test-tc.c
+++ b/src/platform/tests/test-tc.c
@@ -7,7 +7,7 @@
#include "nm-test-utils-core.h"
#include "platform/nmp-object.h"
#include "nm-platform/nmp-netns.h"
-#include "platform/nm-platform-utils.h"
+#include "nm-platform/nm-platform-utils.h"
#include "test-common.h"
static NMPObject *
diff --git a/src/platform/wifi/nm-wifi-utils-nl80211.c b/src/platform/wifi/nm-wifi-utils-nl80211.c
index 0bca7acc46..aae6af1ec8 100644
--- a/src/platform/wifi/nm-wifi-utils-nl80211.c
+++ b/src/platform/wifi/nm-wifi-utils-nl80211.c
@@ -18,7 +18,7 @@
#include "nm-platform/nm-netlink.h"
#include "nm-wifi-utils-private.h"
#include "platform/nm-platform.h"
-#include "platform/nm-platform-utils.h"
+#include "nm-platform/nm-platform-utils.h"
#include "nm-utils.h"
#define _NMLOG_PREFIX_NAME "wifi-nl80211"
diff --git a/src/platform/wifi/nm-wifi-utils-wext.c b/src/platform/wifi/nm-wifi-utils-wext.c
index 4d024174c8..2b070b5abe 100644
--- a/src/platform/wifi/nm-wifi-utils-wext.c
+++ b/src/platform/wifi/nm-wifi-utils-wext.c
@@ -23,7 +23,7 @@
#include "nm-wifi-utils-private.h"
#include "nm-utils.h"
-#include "platform/nm-platform-utils.h"
+#include "nm-platform/nm-platform-utils.h"
#include "nm-core-internal.h"
#include "nm-core-utils.h"
diff --git a/src/platform/wifi/nm-wifi-utils.c b/src/platform/wifi/nm-wifi-utils.c
index a9d5f2484c..66d6a05a75 100644
--- a/src/platform/wifi/nm-wifi-utils.c
+++ b/src/platform/wifi/nm-wifi-utils.c
@@ -19,7 +19,7 @@
#endif
#include "nm-core-utils.h"
-#include "platform/nm-platform-utils.h"
+#include "nm-platform/nm-platform-utils.h"
G_DEFINE_ABSTRACT_TYPE(NMWifiUtils, nm_wifi_utils, G_TYPE_OBJECT)
diff --git a/src/platform/wpan/nm-wpan-utils.c b/src/platform/wpan/nm-wpan-utils.c
index d7c93b19b6..96897ae04d 100644
--- a/src/platform/wpan/nm-wpan-utils.c
+++ b/src/platform/wpan/nm-wpan-utils.c
@@ -11,7 +11,7 @@
#include "nm-platform/nm-netlink.h"
#include "platform/linux/nl802154.h"
-#include "platform/nm-platform-utils.h"
+#include "nm-platform/nm-platform-utils.h"
#define _NMLOG_PREFIX_NAME "wpan-nl802154"
#define _NMLOG(level, domain, ...) \