From f0213e3796b4dd66e546e2de4d677db319f9171b Mon Sep 17 00:00:00 2001 From: Tom Gundersen Date: Mon, 21 Sep 2015 15:53:40 +0200 Subject: networkd: route/address - simplify and unify creators Rename new_dynamic() to simply _new() and reuse that from new_static(). --- src/network/networkd-address.c | 39 +++++++++++++++--------------------- src/network/networkd-address.h | 2 +- src/network/networkd-dhcp4.c | 16 +++++++-------- src/network/networkd-dhcp6.c | 2 +- src/network/networkd-ipv4ll.c | 8 ++++---- src/network/networkd-link.c | 2 +- src/network/networkd-route.c | 45 ++++++++++++++++++++---------------------- src/network/networkd-route.h | 2 +- src/network/test-network.c | 4 ++-- 9 files changed, 55 insertions(+), 65 deletions(-) (limited to 'src/network') diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 388beb5d4c..b2f24ec305 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -30,17 +30,27 @@ #include "networkd.h" #include "networkd-address.h" -static void address_init(Address *address) { - assert(address); +int address_new(Address **ret) { + _cleanup_address_free_ Address *address = NULL; + + address = new0(Address, 1); + if (!address) + return -ENOMEM; address->family = AF_UNSPEC; address->scope = RT_SCOPE_UNIVERSE; address->cinfo.ifa_prefered = CACHE_INFO_INFINITY_LIFE_TIME; address->cinfo.ifa_valid = CACHE_INFO_INFINITY_LIFE_TIME; + + *ret = address; + address = NULL; + + return 0; } int address_new_static(Network *network, unsigned section, Address **ret) { _cleanup_address_free_ Address *address = NULL; + int r; if (section) { address = hashmap_get(network->addresses_by_section, UINT_TO_PTR(section)); @@ -52,11 +62,9 @@ int address_new_static(Network *network, unsigned section, Address **ret) { } } - address = new0(Address, 1); - if (!address) - return -ENOMEM; - - address_init(address); + r = address_new(&address); + if (r < 0) + return r; address->network = network; @@ -74,21 +82,6 @@ int address_new_static(Network *network, unsigned section, Address **ret) { return 0; } -int address_new_dynamic(Address **ret) { - _cleanup_address_free_ Address *address = NULL; - - address = new0(Address, 1); - if (!address) - return -ENOMEM; - - address_init(address); - - *ret = address; - address = NULL; - - return 0; -} - void address_free(Address *address) { if (!address) return; @@ -292,7 +285,7 @@ static int address_acquire(Link *link, Address *original, Address **ret) { } else if (original->family == AF_INET6) in_addr.in6.s6_addr[15] |= 1; - r = address_new_dynamic(&na); + r = address_new(&na); if (r < 0) return r; diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h index 39789a2382..74c0c0be89 100644 --- a/src/network/networkd-address.h +++ b/src/network/networkd-address.h @@ -56,7 +56,7 @@ struct Address { }; int address_new_static(Network *network, unsigned section, Address **ret); -int address_new_dynamic(Address **ret); +int address_new(Address **ret); void address_free(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); diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index 04f04df117..2a0900d5b1 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -72,11 +72,11 @@ static int link_set_dhcp_routes(Link *link) { if (r < 0) return log_link_warning_errno(link, r, "DHCP error: could not get address: %m"); - r = route_new_dynamic(&route, RTPROT_DHCP); + r = route_new(&route, RTPROT_DHCP); if (r < 0) return log_link_error_errno(link, r, "Could not allocate route: %m"); - r = route_new_dynamic(&route_gw, RTPROT_DHCP); + r = route_new(&route_gw, RTPROT_DHCP); if (r < 0) return log_link_error_errno(link, r, "Could not allocate route: %m"); @@ -120,7 +120,7 @@ static int link_set_dhcp_routes(Link *link) { for (i = 0; i < n; i++) { _cleanup_route_free_ Route *route = NULL; - r = route_new_dynamic(&route, RTPROT_DHCP); + r = route_new(&route, RTPROT_DHCP); if (r < 0) return log_link_error_errno(link, r, "Could not allocate route: %m"); @@ -162,7 +162,7 @@ static int dhcp_lease_lost(Link *link) { for (i = 0; i < n; i++) { _cleanup_route_free_ Route *route = NULL; - r = route_new_dynamic(&route, RTPROT_UNSPEC); + r = route_new(&route, RTPROT_UNSPEC); if (r >= 0) { route->family = AF_INET; route->in_addr.in = routes[i].gw_addr; @@ -176,14 +176,14 @@ static int dhcp_lease_lost(Link *link) { } } - r = address_new_dynamic(&address); + r = address_new(&address); if (r >= 0) { r = sd_dhcp_lease_get_router(link->dhcp_lease, &gateway); if (r >= 0) { _cleanup_route_free_ Route *route_gw = NULL; _cleanup_route_free_ Route *route = NULL; - r = route_new_dynamic(&route_gw, RTPROT_UNSPEC); + r = route_new(&route_gw, RTPROT_UNSPEC); if (r >= 0) { route_gw->family = AF_INET; route_gw->dst_addr.in = gateway; @@ -194,7 +194,7 @@ static int dhcp_lease_lost(Link *link) { &link_route_drop_handler); } - r = route_new_dynamic(&route, RTPROT_UNSPEC); + r = route_new(&route, RTPROT_UNSPEC); if (r >= 0) { route->family = AF_INET; route->in_addr.in = gateway; @@ -288,7 +288,7 @@ static int dhcp4_update_address(Link *link, prefixlen = in_addr_netmask_to_prefixlen(netmask); - r = address_new_dynamic(&addr); + r = address_new(&addr); if (r < 0) return r; diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c index 3cb7b8d9ca..a58af06198 100644 --- a/src/network/networkd-dhcp6.c +++ b/src/network/networkd-dhcp6.c @@ -69,7 +69,7 @@ static int dhcp6_address_update(Link *link, struct in6_addr *ip6_addr, int r; _cleanup_address_free_ Address *addr = NULL; - r = address_new_dynamic(&addr); + r = address_new(&addr); if (r < 0) return r; diff --git a/src/network/networkd-ipv4ll.c b/src/network/networkd-ipv4ll.c index 1902b3d23a..f55b00d36c 100644 --- a/src/network/networkd-ipv4ll.c +++ b/src/network/networkd-ipv4ll.c @@ -42,7 +42,7 @@ static int ipv4ll_address_lost(Link *link) { log_link_debug(link, "IPv4 link-local release %u.%u.%u.%u", ADDRESS_FMT_VAL(addr)); - r = address_new_dynamic(&address); + r = address_new(&address); if (r < 0) { log_link_error_errno(link, r, "Could not allocate address: %m"); return r; @@ -55,7 +55,7 @@ static int ipv4ll_address_lost(Link *link) { address_drop(address, link, &link_address_drop_handler); - r = route_new_dynamic(&route, RTPROT_UNSPEC); + r = route_new(&route, RTPROT_UNSPEC); if (r < 0) { log_link_error_errno(link, r, "Could not allocate route: %m"); return r; @@ -133,7 +133,7 @@ static int ipv4ll_address_claimed(sd_ipv4ll *ll, Link *link) { log_link_debug(link, "IPv4 link-local claim %u.%u.%u.%u", ADDRESS_FMT_VAL(address)); - r = address_new_dynamic(&ll_addr); + r = address_new(&ll_addr); if (r < 0) return r; @@ -149,7 +149,7 @@ static int ipv4ll_address_claimed(sd_ipv4ll *ll, Link *link) { link->ipv4ll_address = false; - r = route_new_dynamic(&route, RTPROT_STATIC); + r = route_new(&route, RTPROT_STATIC); if (r < 0) return r; diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index ffc9578e86..e9047dd6a6 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -2074,7 +2074,7 @@ int link_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, voi } } - r = address_new_dynamic(&address); + r = address_new(&address); if (r < 0) return r; diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index ee1ddd81fe..28ce126849 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -26,8 +26,26 @@ #include "networkd.h" #include "networkd-route.h" +int route_new(Route **ret, unsigned char rtm_protocol) { + _cleanup_route_free_ Route *route = NULL; + + route = new0(Route, 1); + if (!route) + return -ENOMEM; + + route->family = AF_UNSPEC; + route->scope = RT_SCOPE_UNIVERSE; + route->protocol = rtm_protocol; + + *ret = route; + route = NULL; + + return 0; +} + int route_new_static(Network *network, unsigned section, Route **ret) { _cleanup_route_free_ Route *route = NULL; + int r; if (section) { route = hashmap_get(network->routes_by_section, @@ -40,13 +58,9 @@ int route_new_static(Network *network, unsigned section, Route **ret) { } } - route = new0(Route, 1); - if (!route) - return -ENOMEM; - - route->family = AF_UNSPEC; - route->scope = RT_SCOPE_UNIVERSE; - route->protocol = RTPROT_STATIC; + r = route_new(&route, RTPROT_STATIC); + if (r < 0) + return r; route->network = network; @@ -64,23 +78,6 @@ int route_new_static(Network *network, unsigned section, Route **ret) { return 0; } -int route_new_dynamic(Route **ret, unsigned char rtm_protocol) { - _cleanup_route_free_ Route *route = NULL; - - route = new0(Route, 1); - if (!route) - return -ENOMEM; - - route->family = AF_UNSPEC; - route->scope = RT_SCOPE_UNIVERSE; - route->protocol = rtm_protocol; - - *ret = route; - route = NULL; - - return 0; -} - void route_free(Route *route) { if (!route) return; diff --git a/src/network/networkd-route.h b/src/network/networkd-route.h index 11e94d44fb..b7e5bfb057 100644 --- a/src/network/networkd-route.h +++ b/src/network/networkd-route.h @@ -46,7 +46,7 @@ struct Route { }; int route_new_static(Network *network, unsigned section, Route **ret); -int route_new_dynamic(Route **ret, unsigned char rtm_protocol); +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); diff --git a/src/network/test-network.c b/src/network/test-network.c index 5909cc790e..80676651a9 100644 --- a/src/network/test-network.c +++ b/src/network/test-network.c @@ -143,8 +143,8 @@ static void test_network_get(Manager *manager, struct udev_device *loopback) { static void test_address_equality(void) { _cleanup_address_free_ Address *a1 = NULL, *a2 = NULL; - assert_se(address_new_dynamic(&a1) >= 0); - assert_se(address_new_dynamic(&a2) >= 0); + assert_se(address_new(&a1) >= 0); + assert_se(address_new(&a2) >= 0); assert_se(address_equal(NULL, NULL)); assert_se(!address_equal(a1, NULL)); -- cgit v1.2.3-54-g00ecf 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') 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 3ac8e5433f20bfb5e12b918252643106a2de52af Mon Sep 17 00:00:00 2001 From: Tom Gundersen Date: Tue, 22 Sep 2015 17:54:27 +0200 Subject: networkd: address - add hash helpers for Address objects Add compare_func and hash_func for the Address object. The notion of address equality is the same as in the kernel, and hashing preserves preserves equality. Two addresses are considered equal if: - they have the same address family, and - they are neither IPv4 nor IPv6 addresses, or - the local addresses are identical, and - they are IPv6 addresses, or - they have the same prefixlength, and - their peer prefixes are identical This fixes a bug in the old equality check, which got the local address and the peer prefix mixed up. --- src/network/networkd-address.c | 149 +++++++++++++++++++++++++++-------------- src/network/test-network.c | 9 +-- 2 files changed, 105 insertions(+), 53 deletions(-) (limited to 'src/network') diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index b2f24ec305..efbdda5939 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -21,11 +21,12 @@ #include -#include "utf8.h" -#include "util.h" #include "conf-parser.h" #include "firewall-util.h" #include "netlink-util.h" +#include "set.h" +#include "utf8.h" +#include "util.h" #include "networkd.h" #include "networkd-address.h" @@ -97,6 +98,103 @@ void address_free(Address *address) { free(address); } +static void address_hash_func(const void *b, struct siphash *state) { + const Address *a = b; + + assert(a); + + siphash24_compress(&a->family, sizeof(a->family), state); + + switch (a->family) { + case AF_INET: + siphash24_compress(&a->prefixlen, sizeof(a->prefixlen), state); + + /* peer prefix */ + if (a->prefixlen != 0) { + uint32_t prefix; + + if (a->in_addr_peer.in.s_addr != 0) + prefix = be32toh(a->in_addr_peer.in.s_addr) >> (32 - a->prefixlen); + else + prefix = be32toh(a->in_addr.in.s_addr) >> (32 - a->prefixlen); + + siphash24_compress(&prefix, sizeof(prefix), state); + } + + /* fallthrough */ + case AF_INET6: + /* local address */ + siphash24_compress(&a->in_addr, FAMILY_ADDRESS_SIZE(a->family), state); + + break; + default: + /* treat any other address family as AF_UNSPEC */ + break; + } +} + +static int address_compare_func(const void *c1, const void *c2) { + const Address *a1 = c1, *a2 = c2; + + if (a1->family < a2->family) + return -1; + if (a1->family > a2->family) + return 1; + + switch (a1->family) { + /* use the same notion of equality as the kernel does */ + case AF_INET: + if (a1->prefixlen < a2->prefixlen) + return -1; + if (a1->prefixlen > a2->prefixlen) + return 1; + + /* compare the peer prefixes */ + if (a1->prefixlen != 0) { + /* make sure we don't try to shift by 32. + * See ISO/IEC 9899:TC3 § 6.5.7.3. */ + uint32_t b1, b2; + + if (a1->in_addr_peer.in.s_addr != 0) + b1 = be32toh(a1->in_addr_peer.in.s_addr) >> (32 - a1->prefixlen); + else + b1 = be32toh(a1->in_addr.in.s_addr) >> (32 - a1->prefixlen); + + if (a2->in_addr_peer.in.s_addr != 0) + b2 = be32toh(a2->in_addr_peer.in.s_addr) >> (32 - a1->prefixlen); + else + b2 = be32toh(a2->in_addr.in.s_addr) >> (32 - a1->prefixlen); + + if (b1 < b2) + return -1; + if (b1 > b2) + return 1; + } + + /* fall-through */ + case AF_INET6: + return memcmp(&a1->in_addr, &a2->in_addr, FAMILY_ADDRESS_SIZE(a1->family)); + default: + /* treat any other address family as AF_UNSPEC */ + return 0; + } +} + +static const struct hash_ops address_hash_ops = { + .hash = address_hash_func, + .compare = address_compare_func +}; + +bool address_equal(Address *a1, Address *a2) { + if (a1 == a2) + return true; + + if (!a1 || !a2) + return false; + + return address_compare_func(a1, a2) == 0; +} + int address_establish(Address *address, Link *link) { bool masq; int r; @@ -572,50 +670,3 @@ int config_parse_label(const char *unit, return 0; } - -bool address_equal(Address *a1, Address *a2) { - /* same object */ - if (a1 == a2) - return true; - - /* one, but not both, is NULL */ - if (!a1 || !a2) - return false; - - if (a1->family != a2->family) - return false; - - switch (a1->family) { - /* use the same notion of equality as the kernel does */ - case AF_UNSPEC: - return true; - - case AF_INET: - if (a1->prefixlen != a2->prefixlen) - return false; - else if (a1->prefixlen == 0) - /* make sure we don't try to shift by 32. - * See ISO/IEC 9899:TC3 § 6.5.7.3. */ - return true; - else { - uint32_t b1, b2; - - b1 = be32toh(a1->in_addr.in.s_addr); - b2 = be32toh(a2->in_addr.in.s_addr); - - return (b1 >> (32 - a1->prefixlen)) == (b2 >> (32 - a1->prefixlen)); - } - - case AF_INET6: { - uint64_t *b1, *b2; - - b1 = (uint64_t*)&a1->in_addr.in6; - b2 = (uint64_t*)&a2->in_addr.in6; - - return (((b1[0] ^ b2[0]) | (b1[1] ^ b2[1])) == 0UL); - } - - default: - assert_not_reached("Invalid address family"); - } -} diff --git a/src/network/test-network.c b/src/network/test-network.c index 80676651a9..bac1d6781d 100644 --- a/src/network/test-network.c +++ b/src/network/test-network.c @@ -158,17 +158,18 @@ static void test_address_equality(void) { assert_se(address_equal(a1, a2)); assert_se(inet_pton(AF_INET, "192.168.3.9", &a1->in_addr.in)); - assert_se(address_equal(a1, a2)); + assert_se(!address_equal(a1, a2)); assert_se(inet_pton(AF_INET, "192.168.3.9", &a2->in_addr.in)); assert_se(address_equal(a1, a2)); + assert_se(inet_pton(AF_INET, "192.168.3.10", &a1->in_addr_peer.in)); + assert_se(address_equal(a1, a2)); + assert_se(inet_pton(AF_INET, "192.168.3.11", &a2->in_addr_peer.in)); + assert_se(address_equal(a1, a2)); a1->prefixlen = 10; assert_se(!address_equal(a1, a2)); a2->prefixlen = 10; assert_se(address_equal(a1, a2)); - assert_se(inet_pton(AF_INET, "192.168.3.10", &a2->in_addr.in)); - assert_se(address_equal(a1, a2)); - a1->family = AF_INET6; assert_se(!address_equal(a1, a2)); -- cgit v1.2.3-54-g00ecf From a2fae7bbb21bdcc9d0a2094b7fd6b364ffbaae86 Mon Sep 17 00:00:00 2001 From: Tom Gundersen Date: Wed, 30 Sep 2015 19:37:52 +0200 Subject: networkd: link/network - correctly align log messages --- src/network/networkd-link.c | 16 ++++++++-------- src/network/networkd-network.c | 8 ++++---- 2 files changed, 12 insertions(+), 12 deletions(-) (limited to 'src/network') diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index e9047dd6a6..1374f44112 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -531,7 +531,7 @@ static int route_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata r = sd_netlink_message_get_errno(m); if (r < 0 && r != -EEXIST) - log_link_warning_errno(link, r, "%-*s: could not set route: %m", IFNAMSIZ, link->ifname); + log_link_warning_errno(link, r, "Could not set route: %m"); if (link->link_messages == 0) { log_link_debug(link, "Routes set"); @@ -585,7 +585,7 @@ int link_route_drop_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userd r = sd_netlink_message_get_errno(m); if (r < 0 && r != -ESRCH) - log_link_warning_errno(link, r, "%-*s: could not drop route: %m", IFNAMSIZ, link->ifname); + log_link_warning_errno(link, r, "Could not drop route: %m"); return 1; } @@ -609,7 +609,7 @@ static int address_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userda r = sd_netlink_message_get_errno(m); if (r < 0 && r != -EEXIST) - log_link_warning_errno(link, r, "%-*s: could not set address: %m", IFNAMSIZ, link->ifname); + log_link_warning_errno(link, r, "could not set address: %m"); else if (r >= 0) link_rtnl_process_address(rtnl, m, link->manager); @@ -867,7 +867,7 @@ int link_address_drop_handler(sd_netlink *rtnl, sd_netlink_message *m, void *use r = sd_netlink_message_get_errno(m); if (r < 0 && r != -EADDRNOTAVAIL) - log_link_warning_errno(link, r, "%-*s: could not drop address: %m", IFNAMSIZ, link->ifname); + log_link_warning_errno(link, r, "Could not drop address: %m"); return 1; } @@ -1019,7 +1019,7 @@ static int set_mtu_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userda r = sd_netlink_message_get_errno(m); if (r < 0) - log_link_warning_errno(link, r, "%-*s: could not set MTU: %m", IFNAMSIZ, link->ifname); + log_link_warning_errno(link, r, "Could not set MTU: %m"); return 1; } @@ -1207,7 +1207,7 @@ static int link_up_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userda if (r < 0) /* we warn but don't fail the link, as it may be brought up later */ - log_link_warning_errno(link, r, "%-*s: could not bring up interface: %m", IFNAMSIZ, link->ifname); + log_link_warning_errno(link, r, "Could not bring up interface: %m"); return 1; } @@ -1294,7 +1294,7 @@ static int link_down_handler(sd_netlink *rtnl, sd_netlink_message *m, void *user r = sd_netlink_message_get_errno(m); if (r < 0) - log_link_warning_errno(link, r, "%-*s: could not bring down interface: %m", IFNAMSIZ, link->ifname); + log_link_warning_errno(link, r, "Could not bring down interface: %m"); return 1; } @@ -1616,7 +1616,7 @@ static int netdev_join_handler(sd_netlink *rtnl, sd_netlink_message *m, void *us r = sd_netlink_message_get_errno(m); if (r < 0 && r != -EEXIST) { - log_link_error_errno(link, r, "%-*s: could not join netdev: %m", IFNAMSIZ, link->ifname); + log_link_error_errno(link, r, "Could not join netdev: %m"); link_enter_failed(link); return 1; } else diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 5d22598fc0..bdee7f1923 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -326,12 +326,12 @@ int network_get(Manager *manager, struct udev_device *device, (void) safe_atou8(attr, &name_assign_type); if (name_assign_type == NET_NAME_ENUM) - log_warning("%-*s: found matching network '%s', based on potentially unpredictable ifname", - IFNAMSIZ, ifname, network->filename); + log_warning("%s: found matching network '%s', based on potentially unpredictable ifname", + ifname, network->filename); else - log_debug("%-*s: found matching network '%s'", IFNAMSIZ, ifname, network->filename); + log_debug("%s: found matching network '%s'", ifname, network->filename); } else - log_debug("%-*s: found matching network '%s'", IFNAMSIZ, ifname, network->filename); + log_debug("%s: found matching network '%s'", ifname, network->filename); *ret = network; return 0; -- cgit v1.2.3-54-g00ecf From 5c416fc40818ee271c4ae89909e7780382aa39bb Mon Sep 17 00:00:00 2001 From: Tom Gundersen Date: Fri, 9 Oct 2015 17:21:15 +0200 Subject: networkd: link - fix error handling in link_add() --- src/network/networkd-link.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'src/network') diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 1374f44112..eebefda2e1 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -2207,8 +2207,10 @@ int link_add(Manager *m, sd_netlink_message *message, Link **ret) { /* not in a container, udev will be around */ sprintf(ifindex_str, "n%d", link->ifindex); device = udev_device_new_from_device_id(m->udev, ifindex_str); - if (!device) - return log_link_warning_errno(link, errno, "Could not find udev device: %m"); + if (!device) { + r = log_link_warning_errno(link, errno, "Could not find udev device: %m"); + goto failed; + } if (udev_device_get_is_initialized(device) <= 0) { /* not yet ready */ @@ -2218,17 +2220,20 @@ int link_add(Manager *m, sd_netlink_message *message, Link **ret) { r = link_initialized(link, device); if (r < 0) - return r; + goto failed; } else { /* we are calling a callback directly, so must take a ref */ link_ref(link); r = link_initialized_and_synced(m->rtnl, NULL, link); if (r < 0) - return r; + goto failed; } return 0; +failed: + link_enter_failed(link); + return r; } static int link_carrier_gained(Link *link) { -- cgit v1.2.3-54-g00ecf From 957325b7637a4d3a16a3cea5e2c6b36faa0e1be7 Mon Sep 17 00:00:00 2001 From: Tom Gundersen Date: Fri, 9 Oct 2015 20:47:34 +0200 Subject: networkd: link - refactor (un)ref --- src/network/networkd-link.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) (limited to 'src/network') diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index eebefda2e1..6c35cafbf5 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -336,15 +336,28 @@ static void link_free(Link *link) { } Link *link_unref(Link *link) { - if (link && (-- link->n_ref <= 0)) - link_free(link); + if (!link) + return NULL; + + assert(link->n_ref > 0); + + link->n_ref --; + + if (link->n_ref > 0) + return NULL; + + link_free(link); return NULL; } Link *link_ref(Link *link) { - if (link) - assert_se(++ link->n_ref >= 2); + if (!link) + return NULL; + + assert(link->n_ref > 0); + + link->n_ref ++; return link; } -- 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') 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') 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') 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') 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 From ce6c77ebf12f80c807ad7589a1fb565fabc6a543 Mon Sep 17 00:00:00 2001 From: Tom Gundersen Date: Mon, 28 Sep 2015 13:30:10 +0200 Subject: networkd: address - introduce address_is_ready() Checks that a given address is not tentative nor deprecated. --- src/network/networkd-address.c | 6 ++++++ src/network/networkd-address.h | 1 + src/network/networkd-link.c | 2 +- 3 files changed, 8 insertions(+), 1 deletion(-) (limited to 'src/network') diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 48715972b6..316ae2e4cb 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -738,3 +738,9 @@ int config_parse_label(const char *unit, return 0; } + +bool address_is_ready(const Address *a) { + assert(a); + + return !(a->flags & (IFA_F_TENTATIVE | IFA_F_DEPRECATED)); +} diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h index 22ac5e95c1..425344fe48 100644 --- a/src/network/networkd-address.h +++ b/src/network/networkd-address.h @@ -67,6 +67,7 @@ int address_configure(Address *address, Link *link, sd_netlink_message_handler_t int address_update(Address *address, Link *link, sd_netlink_message_handler_t callback); int address_remove(Address *address, Link *link, sd_netlink_message_handler_t callback); bool address_equal(Address *a1, Address *a2); +bool address_is_ready(const Address *a); DEFINE_TRIVIAL_CLEANUP_FUNC(Address*, address_free); #define _cleanup_address_free_ _cleanup_(address_freep) diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 78853c8cca..755d9c919d 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -2275,7 +2275,7 @@ static void link_update_operstate(Link *link) { /* if we have carrier, check what addresses we have */ SET_FOREACH(address, link->addresses, i) { - if (address->flags & (IFA_F_TENTATIVE | IFA_F_DEPRECATED)) + if (!address_is_ready(address)) continue; if (address->scope < scope) -- cgit v1.2.3-54-g00ecf