summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Gundersen <teg@jklm.no>2015-09-23 01:53:29 +0200
committerTom Gundersen <teg@jklm.no>2015-10-11 15:04:16 +0200
commitcf1d700da3fe04cd4c27980a292301694be3b05f (patch)
tree1637158da3463b4f94a6522818fd941c95e6cfc4
parent200a0868fcdf7b95f3d8d1fda3aa2aef48d84fdd (diff)
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.
-rw-r--r--src/network/networkd-address-pool.c4
-rw-r--r--src/network/networkd-address.c42
-rw-r--r--src/network/networkd-address.h4
-rw-r--r--src/network/networkd-link.c37
-rw-r--r--src/network/networkd-link.h4
-rw-r--r--src/network/networkd-manager.c14
6 files changed, 72 insertions, 33 deletions
diff --git a/src/network/networkd-address-pool.c b/src/network/networkd-address-pool.c
index d609daafde..b3450c1456 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 efbdda5939..9600b957fe 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 74c0c0be89..0b5be02288 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 fe701d8c84..eb03d72907 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -23,15 +23,16 @@
#include <linux/if.h>
#include <unistd.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 "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 b14ace9358..aaa6aaf178 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 3a733dc3c3..30cb502bed 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);