From ac84b22fc729a291929b0dbc92eed1c97515f4fb Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Sat, 2 May 2015 07:59:59 +0200 Subject: [PATCH] platform: move ethtool_*() to nmp_utils_ethtool_*() --- src/platform/nm-linux-platform.c | 221 ++----------------------------- src/platform/nm-platform-utils.c | 211 +++++++++++++++++++++++++++++ src/platform/nm-platform-utils.h | 16 +++ 3 files changed, 238 insertions(+), 210 deletions(-) diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index e69ff2cfd6..f6342fd38b 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -33,7 +33,6 @@ #include #include #include -#include #include #include #include @@ -363,204 +362,6 @@ _support_user_ipv6ll_detect (const struct rtnl_link *rtnl_link) #endif } -/****************************************************************** - * ethtool - ******************************************************************/ - -static gboolean -ethtool_get (const char *name, gpointer edata) -{ - struct ifreq ifr; - int fd; - - if (!name || !*name) - return FALSE; - - memset (&ifr, 0, sizeof (ifr)); - strncpy (ifr.ifr_name, name, IFNAMSIZ); - ifr.ifr_data = edata; - - fd = socket (PF_INET, SOCK_DGRAM, 0); - if (fd < 0) { - error ("ethtool: Could not open socket."); - return FALSE; - } - - if (ioctl (fd, SIOCETHTOOL, &ifr) < 0) { - debug ("ethtool: Request failed: %s", strerror (errno)); - close (fd); - return FALSE; - } - - close (fd); - return TRUE; -} - -static int -ethtool_get_stringset_index (const char *ifname, int stringset_id, const char *string) -{ - gs_free struct ethtool_sset_info *info = NULL; - gs_free struct ethtool_gstrings *strings = NULL; - guint32 len, i; - - info = g_malloc0 (sizeof (*info) + sizeof (guint32)); - info->cmd = ETHTOOL_GSSET_INFO; - info->reserved = 0; - info->sset_mask = 1ULL << stringset_id; - - if (!ethtool_get (ifname, info)) - return -1; - if (!info->sset_mask) - return -1; - - len = info->data[0]; - - strings = g_malloc0 (sizeof (*strings) + len * ETH_GSTRING_LEN); - strings->cmd = ETHTOOL_GSTRINGS; - strings->string_set = stringset_id; - strings->len = len; - if (!ethtool_get (ifname, strings)) - return -1; - - for (i = 0; i < len; i++) { - if (!strcmp ((char *) &strings->data[i * ETH_GSTRING_LEN], string)) - return i; - } - - return -1; -} - -static gboolean -ethtool_get_driver_info (const char *ifname, - char **out_driver_name, - char **out_driver_version, - char **out_fw_version) -{ - struct ethtool_drvinfo drvinfo = { 0 }; - - if (!ifname) - return FALSE; - - drvinfo.cmd = ETHTOOL_GDRVINFO; - if (!ethtool_get (ifname, &drvinfo)) - return FALSE; - - if (out_driver_name) - *out_driver_name = g_strdup (drvinfo.driver); - if (out_driver_version) - *out_driver_version = g_strdup (drvinfo.version); - if (out_fw_version) - *out_fw_version = g_strdup (drvinfo.fw_version); - - return TRUE; -} - -static gboolean -ethtool_get_permanent_address (const char *ifname, - guint8 *buf, - size_t *length) -{ - gs_free struct ethtool_perm_addr *epaddr = NULL; - - if (!ifname) - return FALSE; - - epaddr = g_malloc0 (sizeof (*epaddr) + NM_UTILS_HWADDR_LEN_MAX); - epaddr->cmd = ETHTOOL_GPERMADDR; - epaddr->size = NM_UTILS_HWADDR_LEN_MAX; - - if (!ethtool_get (ifname, epaddr)) - return FALSE; - if (!nm_ethernet_address_is_valid (epaddr->data, epaddr->size)) - return FALSE; - - g_assert (epaddr->size <= NM_UTILS_HWADDR_LEN_MAX); - memcpy (buf, epaddr->data, epaddr->size); - *length = epaddr->size; - return TRUE; -} - -static gboolean -ethtool_supports_carrier_detect (const char *ifname) -{ - struct ethtool_cmd edata = { .cmd = ETHTOOL_GLINK }; - - /* 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_get (ifname, &edata); -} - -static gboolean -ethtool_supports_vlans (const char *ifname) -{ - gs_free struct ethtool_gfeatures *features = NULL; - int idx, block, bit, size; - - if (!ifname) - return FALSE; - - idx = ethtool_get_stringset_index (ifname, ETH_SS_FEATURES, "vlan-challenged"); - if (idx == -1) { - debug ("vlan-challenged ethtool feature does not exist?"); - return FALSE; - } - - block = idx / 32; - bit = idx % 32; - size = block + 1; - - features = g_malloc0 (sizeof (*features) + size * sizeof (struct ethtool_get_features_block)); - features->cmd = ETHTOOL_GFEATURES; - features->size = size; - - if (!ethtool_get (ifname, features)) - return FALSE; - - return !(features->features[block].active & (1 << bit)); -} - -static int -ethtool_get_peer_ifindex (const char *ifname) -{ - gs_free struct ethtool_stats *stats = NULL; - int peer_ifindex_stat; - - if (!ifname) - return 0; - - peer_ifindex_stat = ethtool_get_stringset_index (ifname, ETH_SS_STATS, "peer_ifindex"); - if (peer_ifindex_stat == -1) { - debug ("%s: peer_ifindex ethtool stat does not exist?", ifname); - return FALSE; - } - - stats = g_malloc0 (sizeof (*stats) + (peer_ifindex_stat + 1) * sizeof (guint64)); - stats->cmd = ETHTOOL_GSTATS; - stats->n_stats = peer_ifindex_stat + 1; - if (!ethtool_get (ifname, stats)) - return 0; - - return stats->data[peer_ifindex_stat]; -} - -static gboolean -ethtool_get_wake_on_lan (const char *ifname) -{ - struct ethtool_wolinfo wol; - - if (!ifname) - return FALSE; - - memset (&wol, 0, sizeof (wol)); - wol.cmd = ETHTOOL_GWOL; - if (!ethtool_get (ifname, &wol)) - return FALSE; - - return wol.wolopts != 0; -} - /****************************************************************** * NMPlatform types and functions ******************************************************************/ @@ -1074,7 +875,7 @@ link_extract_type (NMPlatform *platform, struct rtnl_link *rtnllink) } /* Fallback OVS detection for kernel <= 3.16 */ - if (ethtool_get_driver_info (ifname, &driver, NULL, NULL)) { + if (nmp_utils_ethtool_get_driver_info (ifname, &driver, NULL, NULL)) { if (!g_strcmp0 (driver, "openvswitch")) return NM_LINK_TYPE_OPENVSWITCH; } @@ -1151,7 +952,7 @@ init_link (NMPlatform *platform, NMPlatformLink *info, struct rtnl_link *rtnllin if (!info->driver) info->driver = info->kind; if (!info->driver) { - if (ethtool_get_driver_info (name, &tmp, NULL, NULL)) { + if (nmp_utils_ethtool_get_driver_info (name, &tmp, NULL, NULL)) { info->driver = g_intern_string (tmp); g_free (tmp); } @@ -2834,7 +2635,7 @@ 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 ethtool_supports_carrier_detect (name) || supports_mii_carrier_detect (name); + return nmp_utils_ethtool_supports_carrier_detect (name) || supports_mii_carrier_detect (name); } static gboolean @@ -2846,7 +2647,7 @@ link_supports_vlans (NMPlatform *platform, int ifindex) if (!rtnllink || rtnl_link_get_arptype (rtnllink) != ARPHRD_ETHER) return FALSE; - return ethtool_supports_vlans (rtnl_link_get_name (rtnllink)); + return nmp_utils_ethtool_supports_vlans (rtnl_link_get_name (rtnllink)); } static gboolean @@ -2897,7 +2698,7 @@ link_get_permanent_address (NMPlatform *platform, guint8 *buf, size_t *length) { - return ethtool_get_permanent_address (nm_platform_link_get_name (platform, ifindex), buf, length); + return nmp_utils_ethtool_get_permanent_address (nm_platform_link_get_name (platform, ifindex), buf, length); } static gboolean @@ -3300,7 +3101,7 @@ veth_get_properties (NMPlatform *platform, int ifindex, NMPlatformVethProperties if (!ifname) return FALSE; - peer_ifindex = ethtool_get_peer_ifindex (ifname); + peer_ifindex = nmp_utils_ethtool_get_peer_ifindex (ifname); if (peer_ifindex <= 0) return FALSE; @@ -3803,7 +3604,7 @@ link_get_wake_on_lan (NMPlatform *platform, int ifindex) NMLinkType type = link_get_type (platform, ifindex); if (type == NM_LINK_TYPE_ETHERNET) - return ethtool_get_wake_on_lan (link_get_name (platform, ifindex)); + return nmp_utils_ethtool_get_wake_on_lan (link_get_name (platform, ifindex)); else if (type == NM_LINK_TYPE_WIFI) { WifiData *wifi_data = wifi_get_wifi_data (platform, ifindex); @@ -3822,10 +3623,10 @@ link_get_driver_info (NMPlatform *platform, char **out_driver_version, char **out_fw_version) { - return ethtool_get_driver_info (nm_platform_link_get_name (platform, ifindex), - out_driver_name, - out_driver_version, - out_fw_version); + return nmp_utils_ethtool_get_driver_info (nm_platform_link_get_name (platform, ifindex), + out_driver_name, + out_driver_version, + out_fw_version); } /******************************************************************/ diff --git a/src/platform/nm-platform-utils.c b/src/platform/nm-platform-utils.c index 62127142cb..e13a91dcdc 100644 --- a/src/platform/nm-platform-utils.c +++ b/src/platform/nm-platform-utils.c @@ -20,6 +20,217 @@ #include "nm-platform-utils.h" +#include +#include +#include +#include +#include +#include + +#include "gsystem-local-alloc.h" +#include "nm-utils.h" +#include "NetworkManagerUtils.h" +#include "nm-logging.h" + + +/****************************************************************** + * ethtool + ******************************************************************/ + +static gboolean +ethtool_get (const char *name, gpointer edata) +{ + struct ifreq ifr; + int fd; + + if (!name || !*name) + return FALSE; + + memset (&ifr, 0, sizeof (ifr)); + strncpy (ifr.ifr_name, name, IFNAMSIZ); + ifr.ifr_data = edata; + + fd = socket (PF_INET, SOCK_DGRAM, 0); + if (fd < 0) { + nm_log_err (LOGD_PLATFORM, "ethtool: Could not open socket."); + return FALSE; + } + + if (ioctl (fd, SIOCETHTOOL, &ifr) < 0) { + nm_log_dbg (LOGD_PLATFORM, "ethtool: Request failed: %s", strerror (errno)); + close (fd); + return FALSE; + } + + close (fd); + return TRUE; +} + +static int +ethtool_get_stringset_index (const char *ifname, int stringset_id, const char *string) +{ + gs_free struct ethtool_sset_info *info = NULL; + gs_free struct ethtool_gstrings *strings = NULL; + guint32 len, i; + + info = g_malloc0 (sizeof (*info) + sizeof (guint32)); + info->cmd = ETHTOOL_GSSET_INFO; + info->reserved = 0; + info->sset_mask = 1ULL << stringset_id; + + if (!ethtool_get (ifname, info)) + return -1; + if (!info->sset_mask) + return -1; + + len = info->data[0]; + + strings = g_malloc0 (sizeof (*strings) + len * ETH_GSTRING_LEN); + strings->cmd = ETHTOOL_GSTRINGS; + strings->string_set = stringset_id; + strings->len = len; + if (!ethtool_get (ifname, strings)) + return -1; + + for (i = 0; i < len; i++) { + if (!strcmp ((char *) &strings->data[i * ETH_GSTRING_LEN], string)) + return i; + } + + return -1; +} + +gboolean +nmp_utils_ethtool_get_driver_info (const char *ifname, + char **out_driver_name, + char **out_driver_version, + char **out_fw_version) +{ + struct ethtool_drvinfo drvinfo = { 0 }; + + if (!ifname) + return FALSE; + + drvinfo.cmd = ETHTOOL_GDRVINFO; + if (!ethtool_get (ifname, &drvinfo)) + return FALSE; + + if (out_driver_name) + *out_driver_name = g_strdup (drvinfo.driver); + if (out_driver_version) + *out_driver_version = g_strdup (drvinfo.version); + if (out_fw_version) + *out_fw_version = g_strdup (drvinfo.fw_version); + + return TRUE; +} + +gboolean +nmp_utils_ethtool_get_permanent_address (const char *ifname, + guint8 *buf, + size_t *length) +{ + gs_free struct ethtool_perm_addr *epaddr = NULL; + + if (!ifname) + return FALSE; + + epaddr = g_malloc0 (sizeof (*epaddr) + NM_UTILS_HWADDR_LEN_MAX); + epaddr->cmd = ETHTOOL_GPERMADDR; + epaddr->size = NM_UTILS_HWADDR_LEN_MAX; + + if (!ethtool_get (ifname, epaddr)) + return FALSE; + if (!nm_ethernet_address_is_valid (epaddr->data, epaddr->size)) + return FALSE; + + g_assert (epaddr->size <= NM_UTILS_HWADDR_LEN_MAX); + memcpy (buf, epaddr->data, epaddr->size); + *length = epaddr->size; + return TRUE; +} + +gboolean +nmp_utils_ethtool_supports_carrier_detect (const char *ifname) +{ + struct ethtool_cmd edata = { .cmd = ETHTOOL_GLINK }; + + /* 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_get (ifname, &edata); +} + +gboolean +nmp_utils_ethtool_supports_vlans (const char *ifname) +{ + gs_free struct ethtool_gfeatures *features = NULL; + int idx, block, bit, size; + + if (!ifname) + return FALSE; + + idx = ethtool_get_stringset_index (ifname, ETH_SS_FEATURES, "vlan-challenged"); + if (idx == -1) { + nm_log_dbg (LOGD_PLATFORM, "ethtool: vlan-challenged ethtool feature does not exist for %s?", ifname); + return FALSE; + } + + block = idx / 32; + bit = idx % 32; + size = block + 1; + + features = g_malloc0 (sizeof (*features) + size * sizeof (struct ethtool_get_features_block)); + features->cmd = ETHTOOL_GFEATURES; + features->size = size; + + if (!ethtool_get (ifname, features)) + return FALSE; + + return !(features->features[block].active & (1 << bit)); +} + +int +nmp_utils_ethtool_get_peer_ifindex (const char *ifname) +{ + gs_free struct ethtool_stats *stats = NULL; + int peer_ifindex_stat; + + if (!ifname) + return 0; + + peer_ifindex_stat = ethtool_get_stringset_index (ifname, ETH_SS_STATS, "peer_ifindex"); + if (peer_ifindex_stat == -1) { + nm_log_dbg (LOGD_PLATFORM, "ethtool: peer_ifindex stat for %s does not exist?", ifname); + return FALSE; + } + + stats = g_malloc0 (sizeof (*stats) + (peer_ifindex_stat + 1) * sizeof (guint64)); + stats->cmd = ETHTOOL_GSTATS; + stats->n_stats = peer_ifindex_stat + 1; + if (!ethtool_get (ifname, stats)) + return 0; + + return stats->data[peer_ifindex_stat]; +} + +gboolean +nmp_utils_ethtool_get_wake_on_lan (const char *ifname) +{ + struct ethtool_wolinfo wol; + + if (!ifname) + return FALSE; + + memset (&wol, 0, sizeof (wol)); + wol.cmd = ETHTOOL_GWOL; + if (!ethtool_get (ifname, &wol)) + return FALSE; + + return wol.wolopts != 0; +} + /****************************************************************** * udev ******************************************************************/ diff --git a/src/platform/nm-platform-utils.h b/src/platform/nm-platform-utils.h index 76f285d7d0..ba34a1fcb8 100644 --- a/src/platform/nm-platform-utils.h +++ b/src/platform/nm-platform-utils.h @@ -28,6 +28,22 @@ #include "nm-platform.h" +const char *nmp_utils_ethtool_get_driver (const char *ifname); +gboolean nmp_utils_ethtool_supports_carrier_detect (const char *ifname); +gboolean nmp_utils_ethtool_supports_vlans (const char *ifname); +int nmp_utils_ethtool_get_peer_ifindex (const char *ifname); +gboolean nmp_utils_ethtool_get_wake_on_lan (const char *ifname); + +gboolean nmp_utils_ethtool_get_driver_info (const char *ifname, + char **out_driver_name, + char **out_driver_version, + char **out_fw_version); + +gboolean nmp_utils_ethtool_get_permanent_address (const char *ifname, + guint8 *buf, + size_t *length); + + const char *nmp_utils_udev_get_driver (GUdevDevice *device);