]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
networkd: address - store active addresses in a Set rather than a List
authorTom Gundersen <teg@jklm.no>
Tue, 22 Sep 2015 23:53:29 +0000 (01:53 +0200)
committerTom Gundersen <teg@jklm.no>
Sun, 11 Oct 2015 13:04:16 +0000 (15:04 +0200)
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
src/network/networkd-address.c
src/network/networkd-address.h
src/network/networkd-link.c
src/network/networkd-link.h
src/network/networkd-manager.c

index d609daafde99aa58703d72d27573f5bfc93924cd..b3450c1456644d433b34041988142a84b7491ac1 100644 (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;
 
index efbdda593980c62e57bfdc03e0719e15bcc8a9e9..9600b957fe5ee24dc941cba180eae633635aef55 100644 (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;
index 74c0c0be89878fa7c8e262b38a3a15ad6e681833..0b5be02288fa9581c5b330f3ed86b257973bd7e0 100644 (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);
index fe701d8c847fe948bc6d8f871ed7ff1a63fb0ed4..eb03d729079cb2aa49ebe0e4cf81868479641759 100644 (file)
 #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;
 
index b14ace93581692f6d5381b22a1f6dc6e3fa34cbf..aaa6aaf178d128db00a49102fa1a59de945fd2e9 100644 (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);
 
index 3a733dc3c3e622275173537047ed61116c1ad2c4..30cb502bed11fd08986a70aae1ca72d401470c5c 100644 (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);