]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
udev: introduce device_get_sysattr_value_maybe_from_netlink()
authorYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 15 Sep 2021 04:00:21 +0000 (13:00 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 6 Oct 2021 07:39:52 +0000 (16:39 +0900)
src/udev/udev-netlink.c
src/udev/udev-netlink.h

index 4c93934e3e0bf60de5601981842cd6a0d81aeb3c..d9afdabb1500ae6454a7cb50e9b98d3a436a1ed9 100644 (file)
@@ -1,6 +1,8 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 
+#include "device-private.h"
 #include "netlink-util.h"
+#include "strv.h"
 #include "udev-netlink.h"
 
 void link_info_clear(LinkInfo *info) {
@@ -85,3 +87,141 @@ int link_info_get(sd_netlink **rtnl, int ifindex, LinkInfo *ret) {
         info = LINK_INFO_NULL;
         return 0;
 }
+
+static int cache_unsigned(sd_device *device, const char *attr, uint64_t val) {
+        _cleanup_free_ char *str = NULL;
+        int r;
+
+        assert(device);
+        assert(attr);
+
+        if (device_get_cached_sysattr_value(device, attr, NULL) != -ESTALE)
+                return 0;
+
+        if (asprintf(&str, "%"PRIu64, val) < 0)
+                return -ENOMEM;
+
+        r = device_cache_sysattr_value(device, attr, str);
+        if (r < 0)
+                return r;
+
+        TAKE_PTR(str);
+        return 0;
+}
+
+static int cache_hw_addr(sd_device *device, const char *attr, const struct hw_addr_data *hw_addr) {
+        _cleanup_free_ char *str = NULL;
+        int r;
+
+        assert(device);
+        assert(attr);
+        assert(hw_addr);
+
+        if (device_get_cached_sysattr_value(device, attr, NULL) != -ESTALE)
+                return 0;
+
+        str = new(char, HW_ADDR_TO_STRING_MAX);
+        if (!str)
+                return -ENOMEM;
+
+        r = device_cache_sysattr_value(device, attr, hw_addr_to_string(hw_addr, str));
+        if (r < 0)
+                return r;
+
+        TAKE_PTR(str);
+        return 0;
+}
+
+static int cache_string(sd_device *device, const char *attr, const char *val) {
+        _cleanup_free_ char *str = NULL;
+        int r;
+
+        assert(device);
+        assert(attr);
+
+        if (device_get_cached_sysattr_value(device, attr, NULL) != -ESTALE)
+                return 0;
+
+        if (val) {
+                str = strdup(val);
+                if (!str)
+                        return -ENOMEM;
+        }
+
+        r = device_cache_sysattr_value(device, attr, str);
+        if (r < 0)
+                return r;
+
+        TAKE_PTR(str);
+        return 0;
+}
+
+int device_cache_sysattr_from_link_info(sd_device *device, LinkInfo *info) {
+        int ifindex, r;
+
+        assert(device);
+        assert(info);
+
+        r = sd_device_get_ifindex(device, &ifindex);
+        if (r < 0)
+                return r;
+
+        if (ifindex != info->ifindex)
+                return -EINVAL;
+
+        r = cache_unsigned(device, "type", info->iftype);
+        if (r < 0)
+                return r;
+
+        r = cache_hw_addr(device, "address", &info->hw_addr);
+        if (r < 0)
+                return r;
+
+        r = cache_unsigned(device, "iflink", info->iflink);
+        if (r < 0)
+                return r;
+
+        if (info->support_phys_port_name) {
+                r = cache_string(device, "phys_port_name", info->phys_port_name);
+                if (r < 0)
+                        return r;
+        }
+
+        return 0;
+}
+
+int device_get_sysattr_value_maybe_from_netlink(
+                sd_device *device,
+                sd_netlink **rtnl,
+                const char *sysattr,
+                const char **ret_value) {
+
+        _cleanup_(link_info_clear) LinkInfo info = LINK_INFO_NULL;
+        int ifindex, r;
+
+        assert(device);
+        assert(rtnl);
+        assert(sysattr);
+
+        if (sd_device_get_ifindex(device, &ifindex) < 0)
+                return sd_device_get_sysattr_value(device, sysattr, ret_value);
+
+        if (!STR_IN_SET(sysattr, "type", "address", "iflink", "phys_port_name"))
+                return sd_device_get_sysattr_value(device, sysattr, ret_value);
+
+        r = device_get_cached_sysattr_value(device, sysattr, ret_value);
+        if (r != -ESTALE)
+                return r;
+
+        r = link_info_get(rtnl, ifindex, &info);
+        if (r < 0)
+                return r;
+
+        r = device_cache_sysattr_from_link_info(device, &info);
+        if (r < 0)
+                return r;
+
+        /* Do not use device_get_cached_sysattr_value() here, as kernel may not support
+         * IFLA_PHYS_PORT_NAME, and in that case we need to read the value from sysfs. */
+        return sd_device_get_sysattr_value(device, sysattr, ret_value);
+}
index 286ac198b9fe1dc5be07ecbc2950f5efe4090367..a6ea0d5fe21758eed95105745eb6f5e64829ff3b 100644 (file)
@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 #pragma once
 
+#include "sd-device.h"
 #include "sd-netlink.h"
 
 #include "ether-addr-util.h"
@@ -21,3 +22,9 @@ typedef struct LinkInfo {
 
 void link_info_clear(LinkInfo *info);
 int link_info_get(sd_netlink **rtnl, int ifindex, LinkInfo *ret);
+int device_cache_sysattr_from_link_info(sd_device *device, LinkInfo *info);
+int device_get_sysattr_value_maybe_from_netlink(
+                sd_device *device,
+                sd_netlink **rtnl,
+                const char *sysattr,
+                const char **ret_value);