networkctl: create the sd_device structure just once

This is mostly in preparation for future changes: a proper freeing function
is now called on the LinkInfo items.
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2019-10-23 17:02:18 +02:00
parent b492aea093
commit 172353b110
1 changed files with 33 additions and 26 deletions

View File

@ -125,6 +125,7 @@ typedef struct VxLanInfo {
typedef struct LinkInfo {
char name[IFNAMSIZ+1];
char netdev_kind[NETDEV_KIND_MAX];
sd_device *sd_device;
int ifindex;
unsigned short iftype;
struct ether_addr mac_address;
@ -167,12 +168,23 @@ typedef struct LinkInfo {
bool has_stats:1;
bool has_bitrates:1;
bool has_ethtool_link_info:1;
bool needs_freeing:1;
} LinkInfo;
static int link_info_compare(const LinkInfo *a, const LinkInfo *b) {
return CMP(a->ifindex, b->ifindex);
}
static const LinkInfo* link_info_array_free(LinkInfo *array) {
for (unsigned i = 0; array && array[i].needs_freeing; i++) {
sd_device_unref(array[i].sd_device);
}
return mfree(array);
}
DEFINE_TRIVIAL_CLEANUP_FUNC(LinkInfo*, link_info_array_free);
static int decode_netdev(sd_netlink_message *m, LinkInfo *info) {
const char *received_kind;
int r;
@ -360,7 +372,7 @@ static void acquire_ether_link_info(int *fd, LinkInfo *link) {
static int acquire_link_info(sd_bus *bus, sd_netlink *rtnl, char **patterns, LinkInfo **ret) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
_cleanup_free_ LinkInfo *links = NULL;
_cleanup_(link_info_array_freep) LinkInfo *links = NULL;
_cleanup_close_ int fd = -1;
size_t allocated = 0, c = 0, j;
sd_netlink_message *i;
@ -382,7 +394,7 @@ static int acquire_link_info(sd_bus *bus, sd_netlink *rtnl, char **patterns, Lin
return log_error_errno(r, "Failed to enumerate links: %m");
for (i = reply; i; i = sd_netlink_message_next(i)) {
if (!GREEDY_REALLOC0(links, allocated, c+1))
if (!GREEDY_REALLOC0(links, allocated, c + 2)) /* We keep one trailing one as marker */
return -ENOMEM;
r = decode_link(i, links + c, patterns);
@ -391,6 +403,12 @@ static int acquire_link_info(sd_bus *bus, sd_netlink *rtnl, char **patterns, Lin
if (r == 0)
continue;
links[c].needs_freeing = true;
char devid[2 + DECIMAL_STR_MAX(int)];
xsprintf(devid, "n%i", links[c].ifindex);
(void) sd_device_new_from_device_id(&links[c].sd_device, devid);
acquire_ether_link_info(&fd, &links[c]);
c++;
@ -409,7 +427,7 @@ static int acquire_link_info(sd_bus *bus, sd_netlink *rtnl, char **patterns, Lin
static int list_links(int argc, char *argv[], void *userdata) {
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
_cleanup_free_ LinkInfo *links = NULL;
_cleanup_(link_info_array_freep) LinkInfo *links = NULL;
_cleanup_(table_unrefp) Table *table = NULL;
TableCell *cell;
int c, i, r;
@ -441,10 +459,8 @@ static int list_links(int argc, char *argv[], void *userdata) {
for (i = 0; i < c; i++) {
_cleanup_free_ char *setup_state = NULL, *operational_state = NULL;
_cleanup_(sd_device_unrefp) sd_device *d = NULL;
const char *on_color_operational, *off_color_operational,
*on_color_setup, *off_color_setup;
char devid[2 + DECIMAL_STR_MAX(int)];
_cleanup_free_ char *t = NULL;
(void) sd_network_link_get_operational_state(links[i].ifindex, &operational_state);
@ -455,10 +471,7 @@ static int list_links(int argc, char *argv[], void *userdata) {
setup_state = strdup("unmanaged");
setup_state_to_color(setup_state, &on_color_setup, &off_color_setup);
xsprintf(devid, "n%i", links[i].ifindex);
(void) sd_device_new_from_device_id(&d, devid);
t = link_get_type_string(links[i].iftype, d);
t = link_get_type_string(links[i].iftype, links[i].sd_device);
r = table_add_many(table,
TABLE_INT, links[i].ifindex,
@ -1004,8 +1017,6 @@ static int link_status_one(
_cleanup_strv_free_ char **dns = NULL, **ntp = NULL, **search_domains = NULL, **route_domains = NULL;
_cleanup_free_ char *setup_state = NULL, *operational_state = NULL, *tz = NULL;
_cleanup_(sd_device_unrefp) sd_device *d = NULL;
char devid[2 + DECIMAL_STR_MAX(int)];
_cleanup_free_ char *t = NULL, *network = NULL;
const char *driver = NULL, *path = NULL, *vendor = NULL, *model = NULL, *link = NULL;
const char *on_color_operational, *off_color_operational,
@ -1031,23 +1042,19 @@ static int link_status_one(
(void) sd_network_link_get_route_domains(info->ifindex, &route_domains);
(void) sd_network_link_get_ntp(info->ifindex, &ntp);
xsprintf(devid, "n%i", info->ifindex);
if (info->sd_device) {
(void) sd_device_get_property_value(info->sd_device, "ID_NET_LINK_FILE", &link);
(void) sd_device_get_property_value(info->sd_device, "ID_NET_DRIVER", &driver);
(void) sd_device_get_property_value(info->sd_device, "ID_PATH", &path);
(void) sd_device_new_from_device_id(&d, devid);
if (sd_device_get_property_value(info->sd_device, "ID_VENDOR_FROM_DATABASE", &vendor) < 0)
(void) sd_device_get_property_value(info->sd_device, "ID_VENDOR", &vendor);
if (d) {
(void) sd_device_get_property_value(d, "ID_NET_LINK_FILE", &link);
(void) sd_device_get_property_value(d, "ID_NET_DRIVER", &driver);
(void) sd_device_get_property_value(d, "ID_PATH", &path);
if (sd_device_get_property_value(d, "ID_VENDOR_FROM_DATABASE", &vendor) < 0)
(void) sd_device_get_property_value(d, "ID_VENDOR", &vendor);
if (sd_device_get_property_value(d, "ID_MODEL_FROM_DATABASE", &model) < 0)
(void) sd_device_get_property_value(d, "ID_MODEL", &model);
if (sd_device_get_property_value(info->sd_device, "ID_MODEL_FROM_DATABASE", &model) < 0)
(void) sd_device_get_property_value(info->sd_device, "ID_MODEL", &model);
}
t = link_get_type_string(info->iftype, d);
t = link_get_type_string(info->iftype, info->sd_device);
(void) sd_network_link_get_network_file(info->ifindex, &network);
@ -1430,7 +1437,7 @@ static int link_status(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
_cleanup_(sd_hwdb_unrefp) sd_hwdb *hwdb = NULL;
_cleanup_free_ LinkInfo *links = NULL;
_cleanup_(link_info_array_freep) LinkInfo *links = NULL;
int r, c, i;
(void) pager_open(arg_pager_flags);
@ -1518,7 +1525,7 @@ static void lldp_capabilities_legend(uint16_t x) {
static int link_lldp_status(int argc, char *argv[], void *userdata) {
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
_cleanup_free_ LinkInfo *links = NULL;
_cleanup_(link_info_array_freep) LinkInfo *links = NULL;
_cleanup_(table_unrefp) Table *table = NULL;
int i, r, c, m = 0;
uint16_t all = 0;