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:
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user