networkd: address - store active addresses in a Set rather than a List

We need to be able to look these things up quickly as we will be updating them
continuously and there can in principle be many of them.
This commit is contained in:
Tom Gundersen
2015-10-11 15:04:16 +02:00
parent 200a0868fc
commit cf1d700da3
6 changed files with 73 additions and 34 deletions
+3 -1
View File
@@ -21,6 +21,7 @@
#include "networkd.h"
#include "networkd-address-pool.h"
#include "set.h"
int address_pool_new(
Manager *m,
@@ -96,9 +97,10 @@ static bool address_pool_prefix_is_taken(
HASHMAP_FOREACH(l, p->manager->links, i) {
Address *a;
Iterator j;
/* Don't clash with assigned addresses */
LIST_FOREACH(addresses, a, l->addresses) {
SET_FOREACH(a, l->addresses, j) {
if (a->family != p->family)
continue;
+42
View File
@@ -95,6 +95,9 @@ void address_free(Address *address) {
UINT_TO_PTR(address->section));
}
if (address->link)
set_remove(address->link->addresses, address);
free(address);
}
@@ -195,6 +198,45 @@ bool address_equal(Address *a1, Address *a2) {
return address_compare_func(a1, a2) == 0;
}
int address_add(Link *link, Address *address) {
int r;
assert(link);
assert(address);
r = set_ensure_allocated(&link->addresses, &address_hash_ops);
if (r < 0)
return r;
r = set_put(link->addresses, address);
if (r < 0)
return r;
address->link = link;
return 0;
}
int address_get(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret) {
Address address = {}, *existing;
assert(link);
assert(in_addr);
assert(ret);
address.family = family;
address.in_addr = *in_addr;
address.prefixlen = prefixlen;
existing = set_get(link->addresses, &address);
if (!existing)
return -ENOENT;
*ret = existing;
return 0;
}
int address_establish(Address *address, Link *link) {
bool masq;
int r;
+4
View File
@@ -38,6 +38,8 @@ struct Address {
Network *network;
unsigned section;
Link *link;
int family;
unsigned char prefixlen;
unsigned char scope;
@@ -58,6 +60,8 @@ 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_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);
int address_drop(Address *address, Link *link, sd_netlink_message_handler_t callback);
+14 -25
View File
@@ -23,15 +23,16 @@
#include <linux/if.h>
#include <unistd.h>
#include "bus-util.h"
#include "dhcp-lease-internal.h"
#include "fileio.h"
#include "netlink-util.h"
#include "network-internal.h"
#include "set.h"
#include "socket-util.h"
#include "udev-util.h"
#include "util.h"
#include "virt.h"
#include "fileio.h"
#include "socket-util.h"
#include "bus-util.h"
#include "udev-util.h"
#include "netlink-util.h"
#include "dhcp-lease-internal.h"
#include "network-internal.h"
#include "networkd-link.h"
#include "networkd-netdev.h"
@@ -291,10 +292,10 @@ static void link_free(Link *link) {
if (!link)
return;
while ((address = link->addresses)) {
LIST_REMOVE(addresses, link->addresses, address);
address_free(address);
}
while (!set_isempty(link->addresses))
address_free(set_first(link->addresses));
set_free(link->addresses);
while ((address = link->pool_addresses)) {
LIST_REMOVE(addresses, link->pool_addresses, address);
@@ -2024,19 +2025,6 @@ int link_initialized(Link *link, struct udev_device *device) {
return 0;
}
Address* link_get_equal_address(Link *link, Address *needle) {
Address *i;
assert(link);
assert(needle);
LIST_FOREACH(addresses, i, link->addresses)
if (address_equal(i, needle))
return i;
return NULL;
}
int link_add(Manager *m, sd_netlink_message *message, Link **ret) {
Link *link;
_cleanup_udev_device_unref_ struct udev_device *device = NULL;
@@ -2283,9 +2271,10 @@ static void link_update_operstate(Link *link) {
else if (link_has_carrier(link)) {
Address *address;
uint8_t scope = RT_SCOPE_NOWHERE;
Iterator i;
/* if we have carrier, check what addresses we have */
LIST_FOREACH(addresses, address, link->addresses) {
SET_FOREACH(address, link->addresses, i) {
if (address->flags & (IFA_F_TENTATIVE | IFA_F_DEPRECATED))
continue;
+1 -3
View File
@@ -83,7 +83,7 @@ struct Link {
unsigned link_messages;
unsigned enslaving;
LIST_HEAD(Address, addresses);
Set *addresses;
sd_dhcp_client *dhcp_client;
sd_dhcp_lease *dhcp_lease;
@@ -120,8 +120,6 @@ int link_get(Manager *m, int ifindex, Link **ret);
int link_add(Manager *manager, sd_netlink_message *message, Link **ret);
void link_drop(Link *link);
Address *link_get_equal_address(Link *link, Address *address);
int link_address_drop_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata);
int link_route_drop_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata);
+9 -5
View File
@@ -283,7 +283,7 @@ int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message,
uint16_t type;
_cleanup_address_free_ Address *address = NULL;
unsigned char flags;
Address *existing;
Address *existing = NULL;
char buf[INET6_ADDRSTRLEN], valid_buf[FORMAT_TIMESPAN_MAX];
const char *valid_str = NULL;
int r, ifindex;
@@ -394,7 +394,7 @@ int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message,
USEC_PER_SEC);
}
existing = link_get_equal_address(link, address);
address_get(link, address->family, &address->in_addr, address->prefixlen, &existing);
switch (type) {
case RTM_NEWADDR:
@@ -407,9 +407,14 @@ int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message,
existing->cinfo = address->cinfo;
} else {
log_link_debug(link, "Adding address: %s/%u (valid for %s)", buf, address->prefixlen, valid_str);
r = address_add(link, address);
if (r < 0) {
log_link_warning_errno(link, r, "Failed to add address %s/%u: %m", buf, address->prefixlen);
return 0;
} else
log_link_debug(link, "Adding address: %s/%u (valid for %s)", buf, address->prefixlen, valid_str);
LIST_PREPEND(addresses, link->addresses, address);
address_establish(address, link);
address = NULL;
@@ -424,7 +429,6 @@ int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message,
if (existing) {
log_link_debug(link, "Removing address: %s/%u (valid for %s)", buf, address->prefixlen, valid_str);
address_release(existing, link);
LIST_REMOVE(addresses, link->addresses, existing);
address_free(existing);
} else
log_link_warning(link, "Removing non-existent address: %s/%u (valid for %s)", buf, address->prefixlen, valid_str);