platform: avoid copying arguments for nmp_utils_ethtool_get_driver_info()

We call nmp_utils_ethtool_get_driver_info() twice when receiving a
netlink message, but we don't need a clone of the string values.
Instead, expose a data structure that should be stack allocated
by the caller.
This commit is contained in:
Thomas Haller
2016-12-12 13:47:52 +01:00
parent 16ad046c87
commit d32fb8158b
5 changed files with 52 additions and 36 deletions

View File

@@ -676,21 +676,21 @@ _linktype_get_type (NMPlatform *platform,
return NM_LINK_TYPE_IP6TNL;
if (ifname) {
NMPUtilsEthtoolDriverInfo driver_info;
nm_auto_close int dirfd = -1;
gs_free char *driver = NULL;
gs_free char *devtype = NULL;
char ifname_verified[IFNAMSIZ];
/* Fallback OVS detection for kernel <= 3.16 */
if (nmp_utils_ethtool_get_driver_info (ifindex, &driver, NULL, NULL)) {
if (!g_strcmp0 (driver, "openvswitch"))
if (nmp_utils_ethtool_get_driver_info (ifindex, &driver_info)) {
if (nm_streq (driver_info.driver, "openvswitch"))
return NM_LINK_TYPE_OPENVSWITCH;
if (arptype == 256) {
/* Some s390 CTC-type devices report 256 for the encapsulation type
* for some reason, but we need to call them Ethernet.
*/
if (!g_strcmp0 (driver, "ctcm"))
if (nm_streq (driver_info.driver, "ctcm"))
return NM_LINK_TYPE_ETHERNET;
}
}
@@ -5535,14 +5535,17 @@ link_get_driver_info (NMPlatform *platform,
char **out_fw_version)
{
nm_auto_pop_netns NMPNetns *netns = NULL;
NMPUtilsEthtoolDriverInfo driver_info;
if (!nm_platform_netns_push (platform, &netns))
return FALSE;
return nmp_utils_ethtool_get_driver_info (ifindex,
out_driver_name,
out_driver_version,
out_fw_version);
if (!nmp_utils_ethtool_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));
NM_SET_OUT (out_fw_version, g_strdup (driver_info.fw_version));
return TRUE;
}
/*****************************************************************************/

View File

@@ -172,26 +172,25 @@ ethtool_get_stringset_index (int ifindex, int stringset_id, const char *string)
gboolean
nmp_utils_ethtool_get_driver_info (int ifindex,
char **out_driver_name,
char **out_driver_version,
char **out_fw_version)
NMPUtilsEthtoolDriverInfo *data)
{
struct ethtool_drvinfo drvinfo = { 0 };
struct ethtool_drvinfo *drvinfo;
G_STATIC_ASSERT (sizeof (*data) == sizeof (*drvinfo));
G_STATIC_ASSERT (offsetof (NMPUtilsEthtoolDriverInfo, driver) == offsetof (struct ethtool_drvinfo, driver));
G_STATIC_ASSERT (offsetof (NMPUtilsEthtoolDriverInfo, version) == offsetof (struct ethtool_drvinfo, version));
G_STATIC_ASSERT (offsetof (NMPUtilsEthtoolDriverInfo, fw_version) == offsetof (struct ethtool_drvinfo, fw_version));
G_STATIC_ASSERT (sizeof (data->driver) == sizeof (drvinfo->driver));
G_STATIC_ASSERT (sizeof (data->version) == sizeof (drvinfo->version));
G_STATIC_ASSERT (sizeof (data->fw_version) == sizeof (drvinfo->fw_version));
g_return_val_if_fail (ifindex > 0, FALSE);
g_return_val_if_fail (data, FALSE);
drvinfo.cmd = ETHTOOL_GDRVINFO;
if (!ethtool_get (ifindex, &drvinfo))
return FALSE;
drvinfo = (struct ethtool_drvinfo *) data;
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;
memset (drvinfo, 0, sizeof (*drvinfo));
drvinfo->cmd = ETHTOOL_GDRVINFO;
return ethtool_get (ifindex, drvinfo);
}
gboolean

View File

@@ -38,10 +38,25 @@ gboolean nmp_utils_ethtool_set_wake_on_lan (int ifindex, NMSettingWiredWakeOnLan
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);
typedef struct {
/* We don't want to include <linux/ethtool.h> in header files,
* thus create a ABI compatible version of struct ethtool_drvinfo.*/
guint32 _private_cmd;
char driver[32];
char version[32];
char fw_version[32];
char _private_bus_info[32];
char _private_erom_version[32];
char _private_reserved2[12];
guint32 _private_n_priv_flags;
guint32 _private_n_stats;
guint32 _private_testinfo_len;
guint32 _private_eedump_len;
guint32 _private_regdump_len;
} NMPUtilsEthtoolDriverInfo;
gboolean nmp_utils_ethtool_get_driver_info (int ifindex,
char **out_driver_name,
char **out_driver_version,
char **out_fw_version);
NMPUtilsEthtoolDriverInfo *data);
gboolean nmp_utils_ethtool_get_permanent_address (int ifindex,
guint8 *buf,

View File

@@ -141,13 +141,11 @@ _link_get_driver (GUdevDevice *udev_device, const char *kind, int ifindex)
return kind;
if (ifindex > 0) {
char *d;
NMPUtilsEthtoolDriverInfo driver_info;
if (nmp_utils_ethtool_get_driver_info (ifindex, &d, NULL, NULL)) {
driver = d && d[0] ? g_intern_string (d) : NULL;
g_free (d);
if (driver)
return driver;
if (nmp_utils_ethtool_get_driver_info (ifindex, &driver_info)) {
if (driver_info.driver[0])
return g_intern_string (driver_info.driver);
}
}

View File

@@ -1956,6 +1956,7 @@ test_netns_general (gpointer fixture, gconstpointer test_data)
char sbuf[100];
int i, j, k;
gboolean ethtool_support;
NMPUtilsEthtoolDriverInfo driver_info;
if (_test_netns_check_skip ())
return;
@@ -2026,8 +2027,8 @@ test_netns_general (gpointer fixture, gconstpointer test_data)
* 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 (nmtstp_link_get_typed (platform_1, 0, "dummy1_", NM_LINK_TYPE_DUMMY)->ifindex, NULL, NULL, NULL));
g_assert (nmp_utils_ethtool_get_driver_info (nmtstp_link_get_typed (platform_1, 0, "dummy2a", NM_LINK_TYPE_DUMMY)->ifindex, NULL, NULL, NULL));
g_assert (nmp_utils_ethtool_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 (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);
g_assert_cmpint (nmtstp_run_command ("ethtool -i dummy2a > /dev/null"), ==, 0);
g_assert_cmpint (nmtstp_run_command ("ethtool -i dummy2b 2> /dev/null"), !=, 0);
@@ -2036,8 +2037,8 @@ 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 (nmtstp_link_get_typed (platform_2, 0, "dummy1_", NM_LINK_TYPE_DUMMY)->ifindex, NULL, NULL, NULL));
g_assert (nmp_utils_ethtool_get_driver_info (nmtstp_link_get_typed (platform_2, 0, "dummy2b", NM_LINK_TYPE_DUMMY)->ifindex, NULL, NULL, NULL));
g_assert (nmp_utils_ethtool_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 (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);
g_assert_cmpint (nmtstp_run_command ("ethtool -i dummy2a 2> /dev/null"), !=, 0);
g_assert_cmpint (nmtstp_run_command ("ethtool -i dummy2b > /dev/null"), ==, 0);