From 7d20d3759e375367c36471906ba898c6909d5132 Mon Sep 17 00:00:00 2001 From: Tom Gundersen Date: Fri, 9 Oct 2015 21:36:04 +0200 Subject: networkd: manager - free bus after own objects Freeing links/addresses may trigger sending signals over the bus, so let's make sure the bus stays around until our own objects have been freed. --- src/network/networkd-manager.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'src/network/networkd-manager.c') diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index b4259cafef..e42f2a4c1e 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -477,14 +477,6 @@ void manager_free(Manager *m) { free(m->state_file); - sd_event_source_unref(m->udev_event_source); - udev_monitor_unref(m->udev_monitor); - udev_unref(m->udev); - - sd_bus_unref(m->bus); - sd_bus_slot_unref(m->prepare_for_sleep_slot); - sd_event_source_unref(m->bus_retry_event_source); - while ((link = hashmap_first(m->links))) link_unref(link); hashmap_free(m->links); @@ -504,6 +496,14 @@ void manager_free(Manager *m) { sd_netlink_unref(m->rtnl); sd_event_unref(m->event); + sd_event_source_unref(m->udev_event_source); + udev_monitor_unref(m->udev_monitor); + udev_unref(m->udev); + + sd_bus_unref(m->bus); + sd_bus_slot_unref(m->prepare_for_sleep_slot); + sd_event_source_unref(m->bus_retry_event_source); + free(m); } -- cgit v1.2.3-54-g00ecf From 200a0868fcdf7b95f3d8d1fda3aa2aef48d84fdd Mon Sep 17 00:00:00 2001 From: Tom Gundersen Date: Tue, 22 Sep 2015 17:18:20 +0200 Subject: networkd: address - process in manager.c rather than link.c --- src/network/networkd-dhcp4.c | 2 +- src/network/networkd-dhcp6.c | 2 +- src/network/networkd-ipv4ll.c | 2 +- src/network/networkd-link.c | 164 +--------------------------------------- src/network/networkd-link.h | 3 +- src/network/networkd-manager.c | 166 ++++++++++++++++++++++++++++++++++++++++- src/network/networkd.h | 2 + 7 files changed, 172 insertions(+), 169 deletions(-) (limited to 'src/network/networkd-manager.c') diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index 2a0900d5b1..0b7c016280 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -267,7 +267,7 @@ static int dhcp4_address_handler(sd_netlink *rtnl, sd_netlink_message *m, log_link_error_errno(link, r, "Could not set DHCPv4 address: %m"); link_enter_failed(link); } else if (r >= 0) - link_rtnl_process_address(rtnl, m, link->manager); + manager_rtnl_process_address(rtnl, m, link->manager); link_set_dhcp_routes(link); diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c index a58af06198..2f9ecf7a89 100644 --- a/src/network/networkd-dhcp6.c +++ b/src/network/networkd-dhcp6.c @@ -58,7 +58,7 @@ static int dhcp6_address_handler(sd_netlink *rtnl, sd_netlink_message *m, link_enter_failed(link); } else if (r >= 0) - link_rtnl_process_address(rtnl, m, link->manager); + manager_rtnl_process_address(rtnl, m, link->manager); return 1; } diff --git a/src/network/networkd-ipv4ll.c b/src/network/networkd-ipv4ll.c index f55b00d36c..75d82de516 100644 --- a/src/network/networkd-ipv4ll.c +++ b/src/network/networkd-ipv4ll.c @@ -105,7 +105,7 @@ static int ipv4ll_address_handler(sd_netlink *rtnl, sd_netlink_message *m, void log_link_error_errno(link, r, "could not set ipv4ll address: %m"); link_enter_failed(link); } else if (r >= 0) - link_rtnl_process_address(rtnl, m, link->manager); + manager_rtnl_process_address(rtnl, m, link->manager); link->ipv4ll_address = true; diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 6c35cafbf5..fe701d8c84 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -624,7 +624,7 @@ static int address_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userda if (r < 0 && r != -EEXIST) log_link_warning_errno(link, r, "could not set address: %m"); else if (r >= 0) - link_rtnl_process_address(rtnl, m, link->manager); + manager_rtnl_process_address(rtnl, m, link->manager); if (link->link_messages == 0) { log_link_debug(link, "Addresses set"); @@ -2024,7 +2024,7 @@ int link_initialized(Link *link, struct udev_device *device) { return 0; } -static Address* link_get_equal_address(Link *link, Address *needle) { +Address* link_get_equal_address(Link *link, Address *needle) { Address *i; assert(link); @@ -2037,166 +2037,6 @@ static Address* link_get_equal_address(Link *link, Address *needle) { return NULL; } -int link_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, void *userdata) { - Manager *m = userdata; - Link *link = NULL; - uint16_t type; - _cleanup_address_free_ Address *address = NULL; - unsigned char flags; - Address *existing; - char buf[INET6_ADDRSTRLEN], valid_buf[FORMAT_TIMESPAN_MAX]; - const char *valid_str = NULL; - int r, ifindex; - - assert(rtnl); - assert(message); - assert(m); - - if (sd_netlink_message_is_error(message)) { - r = sd_netlink_message_get_errno(message); - if (r < 0) - log_warning_errno(r, "rtnl: failed to receive address: %m"); - - return 0; - } - - r = sd_netlink_message_get_type(message, &type); - if (r < 0) { - log_warning_errno(r, "rtnl: could not get message type: %m"); - return 0; - } else if (type != RTM_NEWADDR && type != RTM_DELADDR) { - log_warning("rtnl: received unexpected message type when processing address"); - return 0; - } - - r = sd_rtnl_message_addr_get_ifindex(message, &ifindex); - if (r < 0) { - log_warning_errno(r, "rtnl: could not get ifindex from address: %m"); - return 0; - } else if (ifindex <= 0) { - log_warning("rtnl: received address message with invalid ifindex: %d", ifindex); - return 0; - } else { - r = link_get(m, ifindex, &link); - if (r < 0 || !link) { - /* when enumerating we might be out of sync, but we will - * get the address again, so just ignore it */ - if (!m->enumerating) - log_warning("rtnl: received address for nonexistent link (%d), ignoring", ifindex); - return 0; - } - } - - r = address_new(&address); - if (r < 0) - return r; - - r = sd_rtnl_message_addr_get_family(message, &address->family); - if (r < 0 || !IN_SET(address->family, AF_INET, AF_INET6)) { - log_link_warning(link, "rtnl: received address with invalid family, ignoring."); - return 0; - } - - r = sd_rtnl_message_addr_get_prefixlen(message, &address->prefixlen); - if (r < 0) { - log_link_warning_errno(link, r, "rtnl: received address with invalid prefixlen, ignoring: %m"); - return 0; - } - - r = sd_rtnl_message_addr_get_scope(message, &address->scope); - if (r < 0) { - log_link_warning_errno(link, r, "rtnl: received address with invalid scope, ignoring: %m"); - return 0; - } - - r = sd_rtnl_message_addr_get_flags(message, &flags); - if (r < 0) { - log_link_warning_errno(link, r, "rtnl: received address with invalid flags, ignoring: %m"); - return 0; - } - address->flags = flags; - - switch (address->family) { - case AF_INET: - r = sd_netlink_message_read_in_addr(message, IFA_LOCAL, &address->in_addr.in); - if (r < 0) { - log_link_warning_errno(link, r, "rtnl: received address without valid address, ignoring: %m"); - return 0; - } - - break; - - case AF_INET6: - r = sd_netlink_message_read_in6_addr(message, IFA_ADDRESS, &address->in_addr.in6); - if (r < 0) { - log_link_warning_errno(link, r, "rtnl: received address without valid address, ignoring: %m"); - return 0; - } - - break; - - default: - assert_not_reached("invalid address family"); - } - - if (!inet_ntop(address->family, &address->in_addr, buf, INET6_ADDRSTRLEN)) { - log_link_warning(link, "Could not print address"); - return 0; - } - - r = sd_netlink_message_read_cache_info(message, IFA_CACHEINFO, &address->cinfo); - if (r >= 0) { - if (address->cinfo.ifa_valid == CACHE_INFO_INFINITY_LIFE_TIME) - valid_str = "ever"; - else - valid_str = format_timespan(valid_buf, FORMAT_TIMESPAN_MAX, - address->cinfo.ifa_valid * USEC_PER_SEC, - USEC_PER_SEC); - } - - existing = link_get_equal_address(link, address); - - switch (type) { - case RTM_NEWADDR: - if (existing) { - log_link_debug(link, "Updating address: %s/%u (valid for %s)", buf, address->prefixlen, valid_str); - - - existing->scope = address->scope; - existing->flags = address->flags; - existing->cinfo = address->cinfo; - - } 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; - - link_save(link); - } - - break; - - case RTM_DELADDR: - - 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); - - break; - default: - assert_not_reached("Received invalid RTNL message type"); - } - - return 1; -} - int link_add(Manager *m, sd_netlink_message *message, Link **ret) { Link *link; _cleanup_udev_device_unref_ struct udev_device *device = NULL; diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h index 7b219c6854..b14ace9358 100644 --- a/src/network/networkd-link.h +++ b/src/network/networkd-link.h @@ -120,6 +120,8 @@ 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); @@ -129,7 +131,6 @@ int link_initialized(Link *link, struct udev_device *device); void link_client_handler(Link *link); int link_update(Link *link, sd_netlink_message *message); -int link_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, void *userdata); int link_save(Link *link); diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index e42f2a4c1e..3a733dc3c3 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -277,6 +277,166 @@ static int manager_connect_udev(Manager *m) { return 0; } +int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, void *userdata) { + Manager *m = userdata; + Link *link = NULL; + uint16_t type; + _cleanup_address_free_ Address *address = NULL; + unsigned char flags; + Address *existing; + char buf[INET6_ADDRSTRLEN], valid_buf[FORMAT_TIMESPAN_MAX]; + const char *valid_str = NULL; + int r, ifindex; + + assert(rtnl); + assert(message); + assert(m); + + if (sd_netlink_message_is_error(message)) { + r = sd_netlink_message_get_errno(message); + if (r < 0) + log_warning_errno(r, "rtnl: failed to receive address: %m"); + + return 0; + } + + r = sd_netlink_message_get_type(message, &type); + if (r < 0) { + log_warning_errno(r, "rtnl: could not get message type: %m"); + return 0; + } else if (type != RTM_NEWADDR && type != RTM_DELADDR) { + log_warning("rtnl: received unexpected message type when processing address"); + return 0; + } + + r = sd_rtnl_message_addr_get_ifindex(message, &ifindex); + if (r < 0) { + log_warning_errno(r, "rtnl: could not get ifindex from address: %m"); + return 0; + } else if (ifindex <= 0) { + log_warning("rtnl: received address message with invalid ifindex: %d", ifindex); + return 0; + } else { + r = link_get(m, ifindex, &link); + if (r < 0 || !link) { + /* when enumerating we might be out of sync, but we will + * get the address again, so just ignore it */ + if (!m->enumerating) + log_warning("rtnl: received address for nonexistent link (%d), ignoring", ifindex); + return 0; + } + } + + r = address_new(&address); + if (r < 0) + return r; + + r = sd_rtnl_message_addr_get_family(message, &address->family); + if (r < 0 || !IN_SET(address->family, AF_INET, AF_INET6)) { + log_link_warning(link, "rtnl: received address with invalid family, ignoring."); + return 0; + } + + r = sd_rtnl_message_addr_get_prefixlen(message, &address->prefixlen); + if (r < 0) { + log_link_warning_errno(link, r, "rtnl: received address with invalid prefixlen, ignoring: %m"); + return 0; + } + + r = sd_rtnl_message_addr_get_scope(message, &address->scope); + if (r < 0) { + log_link_warning_errno(link, r, "rtnl: received address with invalid scope, ignoring: %m"); + return 0; + } + + r = sd_rtnl_message_addr_get_flags(message, &flags); + if (r < 0) { + log_link_warning_errno(link, r, "rtnl: received address with invalid flags, ignoring: %m"); + return 0; + } + address->flags = flags; + + switch (address->family) { + case AF_INET: + r = sd_netlink_message_read_in_addr(message, IFA_LOCAL, &address->in_addr.in); + if (r < 0) { + log_link_warning_errno(link, r, "rtnl: received address without valid address, ignoring: %m"); + return 0; + } + + break; + + case AF_INET6: + r = sd_netlink_message_read_in6_addr(message, IFA_ADDRESS, &address->in_addr.in6); + if (r < 0) { + log_link_warning_errno(link, r, "rtnl: received address without valid address, ignoring: %m"); + return 0; + } + + break; + + default: + assert_not_reached("invalid address family"); + } + + if (!inet_ntop(address->family, &address->in_addr, buf, INET6_ADDRSTRLEN)) { + log_link_warning(link, "Could not print address"); + return 0; + } + + r = sd_netlink_message_read_cache_info(message, IFA_CACHEINFO, &address->cinfo); + if (r >= 0) { + if (address->cinfo.ifa_valid == CACHE_INFO_INFINITY_LIFE_TIME) + valid_str = "ever"; + else + valid_str = format_timespan(valid_buf, FORMAT_TIMESPAN_MAX, + address->cinfo.ifa_valid * USEC_PER_SEC, + USEC_PER_SEC); + } + + existing = link_get_equal_address(link, address); + + switch (type) { + case RTM_NEWADDR: + if (existing) { + log_link_debug(link, "Updating address: %s/%u (valid for %s)", buf, address->prefixlen, valid_str); + + + existing->scope = address->scope; + existing->flags = address->flags; + existing->cinfo = address->cinfo; + + } 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; + + link_save(link); + } + + break; + + case RTM_DELADDR: + + 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); + + break; + default: + assert_not_reached("Received invalid RTNL message type"); + } + + return 1; +} + static int manager_rtnl_process_link(sd_netlink *rtnl, sd_netlink_message *message, void *userdata) { Manager *m = userdata; Link *link = NULL; @@ -410,11 +570,11 @@ static int manager_connect_rtnl(Manager *m) { if (r < 0) return r; - r = sd_netlink_add_match(m->rtnl, RTM_NEWADDR, &link_rtnl_process_address, m); + r = sd_netlink_add_match(m->rtnl, RTM_NEWADDR, &manager_rtnl_process_address, m); if (r < 0) return r; - r = sd_netlink_add_match(m->rtnl, RTM_DELADDR, &link_rtnl_process_address, m); + r = sd_netlink_add_match(m->rtnl, RTM_DELADDR, &manager_rtnl_process_address, m); if (r < 0) return r; @@ -633,7 +793,7 @@ int manager_rtnl_enumerate_addresses(Manager *m) { m->enumerating = true; - k = link_rtnl_process_address(m->rtnl, addr, m); + k = manager_rtnl_process_address(m->rtnl, addr, m); if (k < 0) r = k; diff --git a/src/network/networkd.h b/src/network/networkd.h index eea57ac158..cbec6d5b7e 100644 --- a/src/network/networkd.h +++ b/src/network/networkd.h @@ -80,6 +80,8 @@ bool manager_should_reload(Manager *m); int manager_rtnl_enumerate_links(Manager *m); int manager_rtnl_enumerate_addresses(Manager *m); +int manager_rtnl_process_address(sd_netlink *nl, sd_netlink_message *message, void *userdata); + int manager_send_changed(Manager *m, const char *property, ...) _sentinel_; int manager_save(Manager *m); -- cgit v1.2.3-54-g00ecf From cf1d700da3fe04cd4c27980a292301694be3b05f Mon Sep 17 00:00:00 2001 From: Tom Gundersen Date: Wed, 23 Sep 2015 01:53:29 +0200 Subject: 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(-) (limited to 'src/network/networkd-manager.c') 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 #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 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); -- cgit v1.2.3-54-g00ecf From 054f0db48775d566e4f55feb7cda0f721a9eb485 Mon Sep 17 00:00:00 2001 From: Tom Gundersen Date: Thu, 24 Sep 2015 01:22:05 +0200 Subject: networkd: manager - avoid unnecessary memory allocation Don't allocate Address objects only to free them again when processing rtnl events. --- src/network/networkd-address.c | 17 +++++++++-- src/network/networkd-address.h | 2 +- src/network/networkd-manager.c | 69 +++++++++++++++++++++--------------------- 3 files changed, 50 insertions(+), 38 deletions(-) (limited to 'src/network/networkd-manager.c') diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 9600b957fe..0414ced48a 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -198,11 +198,21 @@ bool address_equal(Address *a1, Address *a2) { return address_compare_func(a1, a2) == 0; } -int address_add(Link *link, Address *address) { +int address_add(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret) { + _cleanup_address_free_ Address *address = NULL; int r; assert(link); - assert(address); + assert(in_addr); + assert(ret); + + r = address_new(&address); + if (r < 0) + return r; + + address->family = family; + address->in_addr = *in_addr; + address->prefixlen = prefixlen; r = set_ensure_allocated(&link->addresses, &address_hash_ops); if (r < 0) @@ -214,6 +224,9 @@ int address_add(Link *link, Address *address) { address->link = link; + *ret = address; + address = NULL; + return 0; } diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h index 0b5be02288..0d575de131 100644 --- a/src/network/networkd-address.h +++ b/src/network/networkd-address.h @@ -60,7 +60,7 @@ 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_add(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret); 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); diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index 30cb502bed..19527b6509 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -281,9 +281,13 @@ int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, Manager *m = userdata; Link *link = NULL; uint16_t type; - _cleanup_address_free_ Address *address = NULL; unsigned char flags; - Address *existing = NULL; + int family; + unsigned char prefixlen; + unsigned char scope; + union in_addr_union in_addr; + struct ifa_cacheinfo cinfo; + Address *address = NULL; char buf[INET6_ADDRSTRLEN], valid_buf[FORMAT_TIMESPAN_MAX]; const char *valid_str = NULL; int r, ifindex; @@ -327,23 +331,19 @@ int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, } } - r = address_new(&address); - if (r < 0) - return r; - - r = sd_rtnl_message_addr_get_family(message, &address->family); - if (r < 0 || !IN_SET(address->family, AF_INET, AF_INET6)) { + r = sd_rtnl_message_addr_get_family(message, &family); + if (r < 0 || !IN_SET(family, AF_INET, AF_INET6)) { log_link_warning(link, "rtnl: received address with invalid family, ignoring."); return 0; } - r = sd_rtnl_message_addr_get_prefixlen(message, &address->prefixlen); + r = sd_rtnl_message_addr_get_prefixlen(message, &prefixlen); if (r < 0) { log_link_warning_errno(link, r, "rtnl: received address with invalid prefixlen, ignoring: %m"); return 0; } - r = sd_rtnl_message_addr_get_scope(message, &address->scope); + r = sd_rtnl_message_addr_get_scope(message, &scope); if (r < 0) { log_link_warning_errno(link, r, "rtnl: received address with invalid scope, ignoring: %m"); return 0; @@ -354,11 +354,10 @@ int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, log_link_warning_errno(link, r, "rtnl: received address with invalid flags, ignoring: %m"); return 0; } - address->flags = flags; - switch (address->family) { + switch (family) { case AF_INET: - r = sd_netlink_message_read_in_addr(message, IFA_LOCAL, &address->in_addr.in); + r = sd_netlink_message_read_in_addr(message, IFA_LOCAL, &in_addr.in); if (r < 0) { log_link_warning_errno(link, r, "rtnl: received address without valid address, ignoring: %m"); return 0; @@ -367,7 +366,7 @@ int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, break; case AF_INET6: - r = sd_netlink_message_read_in6_addr(message, IFA_ADDRESS, &address->in_addr.in6); + r = sd_netlink_message_read_in6_addr(message, IFA_ADDRESS, &in_addr.in6); if (r < 0) { log_link_warning_errno(link, r, "rtnl: received address without valid address, ignoring: %m"); return 0; @@ -379,46 +378,46 @@ int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, assert_not_reached("invalid address family"); } - if (!inet_ntop(address->family, &address->in_addr, buf, INET6_ADDRSTRLEN)) { + if (!inet_ntop(family, &in_addr, buf, INET6_ADDRSTRLEN)) { log_link_warning(link, "Could not print address"); return 0; } - r = sd_netlink_message_read_cache_info(message, IFA_CACHEINFO, &address->cinfo); + r = sd_netlink_message_read_cache_info(message, IFA_CACHEINFO, &cinfo); if (r >= 0) { - if (address->cinfo.ifa_valid == CACHE_INFO_INFINITY_LIFE_TIME) + if (cinfo.ifa_valid == CACHE_INFO_INFINITY_LIFE_TIME) valid_str = "ever"; else valid_str = format_timespan(valid_buf, FORMAT_TIMESPAN_MAX, - address->cinfo.ifa_valid * USEC_PER_SEC, + cinfo.ifa_valid * USEC_PER_SEC, USEC_PER_SEC); } - address_get(link, address->family, &address->in_addr, address->prefixlen, &existing); + address_get(link, family, &in_addr, prefixlen, &address); switch (type) { case RTM_NEWADDR: - if (existing) { - log_link_debug(link, "Updating address: %s/%u (valid for %s)", buf, address->prefixlen, valid_str); + if (address) { + log_link_debug(link, "Updating address: %s/%u (valid for %s)", buf, prefixlen, valid_str); - - existing->scope = address->scope; - existing->flags = address->flags; - existing->cinfo = address->cinfo; + address->scope = scope; + address->flags = flags; + address->cinfo = cinfo; } else { - r = address_add(link, address); + r = address_add(link, family, &in_addr, prefixlen, &address); if (r < 0) { - log_link_warning_errno(link, r, "Failed to add address %s/%u: %m", buf, address->prefixlen); + log_link_warning_errno(link, r, "Failed to add address %s/%u: %m", buf, prefixlen); return 0; } else - log_link_debug(link, "Adding address: %s/%u (valid for %s)", buf, address->prefixlen, valid_str); + log_link_debug(link, "Adding address: %s/%u (valid for %s)", buf, prefixlen, valid_str); + address->scope = scope; + address->flags = flags; + address->cinfo = cinfo; address_establish(address, link); - address = NULL; - link_save(link); } @@ -426,12 +425,12 @@ int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, case RTM_DELADDR: - if (existing) { - log_link_debug(link, "Removing address: %s/%u (valid for %s)", buf, address->prefixlen, valid_str); - address_release(existing, link); - address_free(existing); + if (address) { + log_link_debug(link, "Removing address: %s/%u (valid for %s)", buf, prefixlen, valid_str); + address_release(address, link); + address_free(address); } else - log_link_warning(link, "Removing non-existent address: %s/%u (valid for %s)", buf, address->prefixlen, valid_str); + log_link_warning(link, "Removing non-existent address: %s/%u (valid for %s)", buf, prefixlen, valid_str); break; default: -- cgit v1.2.3-54-g00ecf From 91b5f997316ddc77d26f9a7a5e24c335484586bd Mon Sep 17 00:00:00 2001 From: Tom Gundersen Date: Thu, 24 Sep 2015 15:25:20 +0200 Subject: networkd: make address_{establish,release}() static No need to expose these functions, but rather call them from address_{add,drop}. --- src/network/networkd-address.c | 103 +++++++++++++++++++++++------------------ src/network/networkd-address.h | 5 +- src/network/networkd-dhcp4.c | 14 +++--- src/network/networkd-ipv4ll.c | 4 +- src/network/networkd-link.c | 4 +- src/network/networkd-link.h | 4 +- src/network/networkd-manager.c | 5 +- src/network/networkd-route.c | 2 +- src/network/networkd-route.h | 2 +- 9 files changed, 76 insertions(+), 67 deletions(-) (limited to 'src/network/networkd-manager.c') diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 0414ced48a..48715972b6 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -198,6 +198,33 @@ bool address_equal(Address *a1, Address *a2) { return address_compare_func(a1, a2) == 0; } +static int address_establish(Address *address, Link *link) { + bool masq; + int r; + + assert(address); + assert(link); + + masq = link->network && + link->network->ip_masquerade && + address->family == AF_INET && + address->scope < RT_SCOPE_LINK; + + /* Add firewall entry if this is requested */ + if (address->ip_masquerade_done != masq) { + union in_addr_union masked = address->in_addr; + in_addr_mask(address->family, &masked, address->prefixlen); + + r = fw_add_masquerade(masq, AF_INET, 0, &masked, address->prefixlen, NULL, NULL, 0); + if (r < 0) + log_link_warning_errno(link, r, "Could not enable IP masquerading: %m"); + + address->ip_masquerade_done = masq; + } + + return 0; +} + int address_add(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret) { _cleanup_address_free_ Address *address = NULL; int r; @@ -224,81 +251,67 @@ int address_add(Link *link, int family, const union in_addr_union *in_addr, unsi address->link = link; + r = address_establish(address, link); + if (r < 0) + return r; + *ret = address; address = NULL; 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; +static int address_release(Address *address, Link *link) { int r; assert(address); assert(link); - masq = link->network && - link->network->ip_masquerade && - address->family == AF_INET && - address->scope < RT_SCOPE_LINK; - - /* Add firewall entry if this is requested */ - if (address->ip_masquerade_done != masq) { + /* Remove masquerading firewall entry if it was added */ + if (address->ip_masquerade_done) { union in_addr_union masked = address->in_addr; in_addr_mask(address->family, &masked, address->prefixlen); - r = fw_add_masquerade(masq, AF_INET, 0, &masked, address->prefixlen, NULL, NULL, 0); + r = fw_add_masquerade(false, AF_INET, 0, &masked, address->prefixlen, NULL, NULL, 0); if (r < 0) - log_link_warning_errno(link, r, "Could not enable IP masquerading: %m"); + log_link_warning_errno(link, r, "Failed to disable IP masquerading: %m"); - address->ip_masquerade_done = masq; + address->ip_masquerade_done = false; } return 0; } -int address_release(Address *address, Link *link) { - int r; - +int address_drop(Address *address) { assert(address); + + address_release(address, address->link); + address_free(address); + + 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); - /* Remove masquerading firewall entry if it was added */ - if (address->ip_masquerade_done) { - union in_addr_union masked = address->in_addr; - in_addr_mask(address->family, &masked, address->prefixlen); + address.family = family; + address.in_addr = *in_addr; + address.prefixlen = prefixlen; - r = fw_add_masquerade(false, AF_INET, 0, &masked, address->prefixlen, NULL, NULL, 0); - if (r < 0) - log_link_warning_errno(link, r, "Failed to disable IP masquerading: %m"); + existing = set_get(link->addresses, &address); + if (!existing) + return -ENOENT; - address->ip_masquerade_done = false; - } + *ret = existing; return 0; } -int address_drop(Address *address, Link *link, +int address_remove(Address *address, Link *link, sd_netlink_message_handler_t callback) { _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL; int r; diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h index 0d575de131..22ac5e95c1 100644 --- a/src/network/networkd-address.h +++ b/src/network/networkd-address.h @@ -62,11 +62,10 @@ int address_new(Address **ret); void address_free(Address *address); int address_add(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret); int address_get(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret); +int address_drop(Address *address); 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); -int address_establish(Address *address, Link *link); -int address_release(Address *address, Link *link); +int address_remove(Address *address, Link *link, sd_netlink_message_handler_t callback); bool address_equal(Address *a1, Address *a2); DEFINE_TRIVIAL_CLEANUP_FUNC(Address*, address_free); diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index 0b7c016280..5d9bfcea7c 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -169,8 +169,8 @@ static int dhcp_lease_lost(Link *link) { route->dst_addr.in = routes[i].dst_addr; route->dst_prefixlen = routes[i].dst_prefixlen; - route_drop(route, link, - &link_route_drop_handler); + route_remove(route, link, + &link_route_remove_handler); } } } @@ -190,8 +190,8 @@ static int dhcp_lease_lost(Link *link) { route_gw->dst_prefixlen = 32; route_gw->scope = RT_SCOPE_LINK; - route_drop(route_gw, link, - &link_route_drop_handler); + route_remove(route_gw, link, + &link_route_remove_handler); } r = route_new(&route, RTPROT_UNSPEC); @@ -199,8 +199,8 @@ static int dhcp_lease_lost(Link *link) { route->family = AF_INET; route->in_addr.in = gateway; - route_drop(route, link, - &link_route_drop_handler); + route_remove(route, link, + &link_route_remove_handler); } } @@ -214,7 +214,7 @@ static int dhcp_lease_lost(Link *link) { address->in_addr.in = addr; address->prefixlen = prefixlen; - address_drop(address, link, &link_address_drop_handler); + address_remove(address, link, &link_address_remove_handler); } } diff --git a/src/network/networkd-ipv4ll.c b/src/network/networkd-ipv4ll.c index 75d82de516..01ee9f9f4a 100644 --- a/src/network/networkd-ipv4ll.c +++ b/src/network/networkd-ipv4ll.c @@ -53,7 +53,7 @@ static int ipv4ll_address_lost(Link *link) { address->prefixlen = 16; address->scope = RT_SCOPE_LINK; - address_drop(address, link, &link_address_drop_handler); + address_remove(address, link, &link_address_remove_handler); r = route_new(&route, RTPROT_UNSPEC); if (r < 0) { @@ -65,7 +65,7 @@ static int ipv4ll_address_lost(Link *link) { route->scope = RT_SCOPE_LINK; route->metrics = IPV4LL_ROUTE_METRIC; - route_drop(route, link, &link_route_drop_handler); + route_remove(route, link, &link_route_remove_handler); link_client_handler(link); diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index eb03d72907..78853c8cca 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -586,7 +586,7 @@ static int link_enter_set_routes(Link *link) { return 0; } -int link_route_drop_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { +int link_route_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { _cleanup_link_unref_ Link *link = userdata; int r; @@ -868,7 +868,7 @@ static int link_enter_set_addresses(Link *link) { return 0; } -int link_address_drop_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { +int link_address_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { _cleanup_link_unref_ Link *link = userdata; int r; diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h index aaa6aaf178..b81bae3830 100644 --- a/src/network/networkd-link.h +++ b/src/network/networkd-link.h @@ -120,8 +120,8 @@ 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); -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); +int link_address_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata); +int link_route_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata); void link_enter_failed(Link *link); int link_initialized(Link *link, struct udev_device *device); diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index 19527b6509..07e47b668c 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -416,8 +416,6 @@ int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, address->flags = flags; address->cinfo = cinfo; - address_establish(address, link); - link_save(link); } @@ -427,8 +425,7 @@ int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, if (address) { log_link_debug(link, "Removing address: %s/%u (valid for %s)", buf, prefixlen, valid_str); - address_release(address, link); - address_free(address); + address_drop(address); } else log_link_warning(link, "Removing non-existent address: %s/%u (valid for %s)", buf, prefixlen, valid_str); diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index 28ce126849..1c8302ffaa 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -93,7 +93,7 @@ void route_free(Route *route) { free(route); } -int route_drop(Route *route, Link *link, +int route_remove(Route *route, Link *link, sd_netlink_message_handler_t callback) { _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL; int r; diff --git a/src/network/networkd-route.h b/src/network/networkd-route.h index b7e5bfb057..e3ed1be866 100644 --- a/src/network/networkd-route.h +++ b/src/network/networkd-route.h @@ -49,7 +49,7 @@ int route_new_static(Network *network, unsigned section, Route **ret); int route_new(Route **ret, unsigned char rtm_protocol); void route_free(Route *route); int route_configure(Route *route, Link *link, sd_netlink_message_handler_t callback); -int route_drop(Route *route, Link *link, sd_netlink_message_handler_t callback); +int route_remove(Route *route, Link *link, sd_netlink_message_handler_t callback); DEFINE_TRIVIAL_CLEANUP_FUNC(Route*, route_free); #define _cleanup_route_free_ _cleanup_(route_freep) -- cgit v1.2.3-54-g00ecf