From d9ea90598fe99efbf97fd2b9f7d8ae7539cde1a3 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 15 Sep 2021 13:00:21 +0900 Subject: [PATCH] udev: introduce device_get_sysattr_value_maybe_from_netlink() --- src/udev/udev-netlink.c | 140 ++++++++++++++++++++++++++++++++++++++++ src/udev/udev-netlink.h | 7 ++ 2 files changed, 147 insertions(+) diff --git a/src/udev/udev-netlink.c b/src/udev/udev-netlink.c index 4c93934e3e0..d9afdabb150 100644 --- a/src/udev/udev-netlink.c +++ b/src/udev/udev-netlink.c @@ -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); +} diff --git a/src/udev/udev-netlink.h b/src/udev/udev-netlink.h index 286ac198b9f..a6ea0d5fe21 100644 --- a/src/udev/udev-netlink.h +++ b/src/udev/udev-netlink.h @@ -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); -- 2.47.3