networkd: manager - avoid unnecessary memory allocation
Don't allocate Address objects only to free them again when processing rtnl events.
This commit is contained in:
parent
cf1d700da3
commit
054f0db487
|
@ -198,11 +198,21 @@ bool address_equal(Address *a1, Address *a2) {
|
|||
return address_compare_func(a1, a2) == 0;
|
||||
}
|
||||
|
||||
int address_add(Link *link, Address *address) {
|
||||
int address_add(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret) {
|
||||
_cleanup_address_free_ Address *address = NULL;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(address);
|
||||
assert(in_addr);
|
||||
assert(ret);
|
||||
|
||||
r = address_new(&address);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
address->family = family;
|
||||
address->in_addr = *in_addr;
|
||||
address->prefixlen = prefixlen;
|
||||
|
||||
r = set_ensure_allocated(&link->addresses, &address_hash_ops);
|
||||
if (r < 0)
|
||||
|
@ -214,6 +224,9 @@ int address_add(Link *link, Address *address) {
|
|||
|
||||
address->link = link;
|
||||
|
||||
*ret = address;
|
||||
address = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@ struct Address {
|
|||
int address_new_static(Network *network, unsigned section, Address **ret);
|
||||
int address_new(Address **ret);
|
||||
void address_free(Address *address);
|
||||
int address_add(Link *link, Address *address);
|
||||
int address_add(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret);
|
||||
int address_get(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret);
|
||||
int address_configure(Address *address, Link *link, sd_netlink_message_handler_t callback);
|
||||
int address_update(Address *address, Link *link, sd_netlink_message_handler_t callback);
|
||||
|
|
|
@ -281,9 +281,13 @@ int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message,
|
|||
Manager *m = userdata;
|
||||
Link *link = NULL;
|
||||
uint16_t type;
|
||||
_cleanup_address_free_ Address *address = NULL;
|
||||
unsigned char flags;
|
||||
Address *existing = NULL;
|
||||
int family;
|
||||
unsigned char prefixlen;
|
||||
unsigned char scope;
|
||||
union in_addr_union in_addr;
|
||||
struct ifa_cacheinfo cinfo;
|
||||
Address *address = NULL;
|
||||
char buf[INET6_ADDRSTRLEN], valid_buf[FORMAT_TIMESPAN_MAX];
|
||||
const char *valid_str = NULL;
|
||||
int r, ifindex;
|
||||
|
@ -327,23 +331,19 @@ int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message,
|
|||
}
|
||||
}
|
||||
|
||||
r = address_new(&address);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_rtnl_message_addr_get_family(message, &address->family);
|
||||
if (r < 0 || !IN_SET(address->family, AF_INET, AF_INET6)) {
|
||||
r = sd_rtnl_message_addr_get_family(message, &family);
|
||||
if (r < 0 || !IN_SET(family, AF_INET, AF_INET6)) {
|
||||
log_link_warning(link, "rtnl: received address with invalid family, ignoring.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = sd_rtnl_message_addr_get_prefixlen(message, &address->prefixlen);
|
||||
r = sd_rtnl_message_addr_get_prefixlen(message, &prefixlen);
|
||||
if (r < 0) {
|
||||
log_link_warning_errno(link, r, "rtnl: received address with invalid prefixlen, ignoring: %m");
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = sd_rtnl_message_addr_get_scope(message, &address->scope);
|
||||
r = sd_rtnl_message_addr_get_scope(message, &scope);
|
||||
if (r < 0) {
|
||||
log_link_warning_errno(link, r, "rtnl: received address with invalid scope, ignoring: %m");
|
||||
return 0;
|
||||
|
@ -354,11 +354,10 @@ int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message,
|
|||
log_link_warning_errno(link, r, "rtnl: received address with invalid flags, ignoring: %m");
|
||||
return 0;
|
||||
}
|
||||
address->flags = flags;
|
||||
|
||||
switch (address->family) {
|
||||
switch (family) {
|
||||
case AF_INET:
|
||||
r = sd_netlink_message_read_in_addr(message, IFA_LOCAL, &address->in_addr.in);
|
||||
r = sd_netlink_message_read_in_addr(message, IFA_LOCAL, &in_addr.in);
|
||||
if (r < 0) {
|
||||
log_link_warning_errno(link, r, "rtnl: received address without valid address, ignoring: %m");
|
||||
return 0;
|
||||
|
@ -367,7 +366,7 @@ int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message,
|
|||
break;
|
||||
|
||||
case AF_INET6:
|
||||
r = sd_netlink_message_read_in6_addr(message, IFA_ADDRESS, &address->in_addr.in6);
|
||||
r = sd_netlink_message_read_in6_addr(message, IFA_ADDRESS, &in_addr.in6);
|
||||
if (r < 0) {
|
||||
log_link_warning_errno(link, r, "rtnl: received address without valid address, ignoring: %m");
|
||||
return 0;
|
||||
|
@ -379,46 +378,46 @@ int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message,
|
|||
assert_not_reached("invalid address family");
|
||||
}
|
||||
|
||||
if (!inet_ntop(address->family, &address->in_addr, buf, INET6_ADDRSTRLEN)) {
|
||||
if (!inet_ntop(family, &in_addr, buf, INET6_ADDRSTRLEN)) {
|
||||
log_link_warning(link, "Could not print address");
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = sd_netlink_message_read_cache_info(message, IFA_CACHEINFO, &address->cinfo);
|
||||
r = sd_netlink_message_read_cache_info(message, IFA_CACHEINFO, &cinfo);
|
||||
if (r >= 0) {
|
||||
if (address->cinfo.ifa_valid == CACHE_INFO_INFINITY_LIFE_TIME)
|
||||
if (cinfo.ifa_valid == CACHE_INFO_INFINITY_LIFE_TIME)
|
||||
valid_str = "ever";
|
||||
else
|
||||
valid_str = format_timespan(valid_buf, FORMAT_TIMESPAN_MAX,
|
||||
address->cinfo.ifa_valid * USEC_PER_SEC,
|
||||
cinfo.ifa_valid * USEC_PER_SEC,
|
||||
USEC_PER_SEC);
|
||||
}
|
||||
|
||||
address_get(link, address->family, &address->in_addr, address->prefixlen, &existing);
|
||||
address_get(link, family, &in_addr, prefixlen, &address);
|
||||
|
||||
switch (type) {
|
||||
case RTM_NEWADDR:
|
||||
if (existing) {
|
||||
log_link_debug(link, "Updating address: %s/%u (valid for %s)", buf, address->prefixlen, valid_str);
|
||||
if (address) {
|
||||
log_link_debug(link, "Updating address: %s/%u (valid for %s)", buf, prefixlen, valid_str);
|
||||
|
||||
|
||||
existing->scope = address->scope;
|
||||
existing->flags = address->flags;
|
||||
existing->cinfo = address->cinfo;
|
||||
address->scope = scope;
|
||||
address->flags = flags;
|
||||
address->cinfo = cinfo;
|
||||
|
||||
} else {
|
||||
r = address_add(link, address);
|
||||
r = address_add(link, family, &in_addr, prefixlen, &address);
|
||||
if (r < 0) {
|
||||
log_link_warning_errno(link, r, "Failed to add address %s/%u: %m", buf, address->prefixlen);
|
||||
log_link_warning_errno(link, r, "Failed to add address %s/%u: %m", buf, prefixlen);
|
||||
return 0;
|
||||
} else
|
||||
log_link_debug(link, "Adding address: %s/%u (valid for %s)", buf, address->prefixlen, valid_str);
|
||||
log_link_debug(link, "Adding address: %s/%u (valid for %s)", buf, prefixlen, valid_str);
|
||||
|
||||
address->scope = scope;
|
||||
address->flags = flags;
|
||||
address->cinfo = cinfo;
|
||||
|
||||
address_establish(address, link);
|
||||
|
||||
address = NULL;
|
||||
|
||||
link_save(link);
|
||||
}
|
||||
|
||||
|
@ -426,12 +425,12 @@ int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message,
|
|||
|
||||
case RTM_DELADDR:
|
||||
|
||||
if (existing) {
|
||||
log_link_debug(link, "Removing address: %s/%u (valid for %s)", buf, address->prefixlen, valid_str);
|
||||
address_release(existing, link);
|
||||
address_free(existing);
|
||||
if (address) {
|
||||
log_link_debug(link, "Removing address: %s/%u (valid for %s)", buf, prefixlen, valid_str);
|
||||
address_release(address, link);
|
||||
address_free(address);
|
||||
} else
|
||||
log_link_warning(link, "Removing non-existent address: %s/%u (valid for %s)", buf, address->prefixlen, valid_str);
|
||||
log_link_warning(link, "Removing non-existent address: %s/%u (valid for %s)", buf, prefixlen, valid_str);
|
||||
|
||||
break;
|
||||
default:
|
||||
|
|
Loading…
Reference in a new issue