From cf1d700da3fe04cd4c27980a292301694be3b05f Mon Sep 17 00:00:00 2001 From: Tom Gundersen Date: Wed, 23 Sep 2015 01:53:29 +0200 Subject: [PATCH] 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. --- src/network/networkd-address-pool.c | 4 ++- src/network/networkd-address.c | 42 +++++++++++++++++++++++++++++ src/network/networkd-address.h | 4 +++ src/network/networkd-link.c | 37 +++++++++---------------- src/network/networkd-link.h | 4 +-- src/network/networkd-manager.c | 14 ++++++---- 6 files changed, 72 insertions(+), 33 deletions(-) diff --git a/src/network/networkd-address-pool.c b/src/network/networkd-address-pool.c index d609daafde9..b3450c14566 100644 --- a/src/network/networkd-address-pool.c +++ b/src/network/networkd-address-pool.c @@ -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; diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index efbdda59398..9600b957fe5 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -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; diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h index 74c0c0be898..0b5be02288f 100644 --- a/src/network/networkd-address.h +++ b/src/network/networkd-address.h @@ -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); diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index fe701d8c847..eb03d729079 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -23,15 +23,16 @@ #include #include -#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 "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 "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; diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h index b14ace93581..aaa6aaf178d 100644 --- a/src/network/networkd-link.h +++ b/src/network/networkd-link.h @@ -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); diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index 3a733dc3c3e..30cb502bed1 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -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); -- 2.39.2