Commit f3126202 authored by Thomas Haller's avatar Thomas Haller
Browse files

device: emit IP address changes in queued_ip_config_change() only once

We first iterate over addresses that might have failed IPv6 DAD and
update the state in NMNDisc.

However, while we do that, don't yet invoke the changed signal.
Otherwise, we will invoke it multiple times (in case multiple addresses
failed). Instead, keep track of whether something changed, and handle
it once a bit later.
parent e2c13af8
......@@ -12296,7 +12296,6 @@ queued_ip_config_change (NMDevice *self, int addr_family)
if (!IS_IPv4) {
NMPlatform *platform;
gboolean need_ipv6ll = FALSE;
GSList *dad6_failed_addrs, *iter;
dad6_failed_addrs = g_steal_pointer (&priv->dad6_failed_addrs);
......@@ -12304,6 +12303,9 @@ queued_ip_config_change (NMDevice *self, int addr_family)
if ( priv->state < NM_DEVICE_STATE_DEACTIVATING
&& (platform = nm_device_get_platform (self))
&& nm_platform_link_get (platform, priv->ifindex)) {
gboolean need_ipv6ll = FALSE;
NMNDiscConfigMap ndisc_config_changed = NM_NDISC_CONFIG_NONE;
/* Handle DAD failures */
for (iter = dad6_failed_addrs; iter; iter = iter->next) {
const NMPObject *obj = iter->data;
......@@ -12320,9 +12322,12 @@ queued_ip_config_change (NMDevice *self, int addr_family)
if (IN6_IS_ADDR_LINKLOCAL (&addr->address))
need_ipv6ll = TRUE;
else if (priv->ndisc)
nm_ndisc_dad_failed (priv->ndisc, &addr->address);
ndisc_config_changed |= nm_ndisc_dad_failed (priv->ndisc, &addr->address, FALSE);
}
if (ndisc_config_changed != NM_NDISC_CONFIG_NONE)
nm_ndisc_emit_config_change (priv->ndisc, ndisc_config_changed);
/* If no IPv6 link-local address exists but other addresses do then we
* must add the LL address to remain conformant with RFC 3513 chapter 2.1
* ("Addressing Model"): "All interfaces are required to have at least
......@@ -12331,7 +12336,6 @@ queued_ip_config_change (NMDevice *self, int addr_family)
if ( priv->ip_config_6
&& nm_ip6_config_get_num_addresses (priv->ip_config_6))
need_ipv6ll = TRUE;
if (need_ipv6ll)
check_and_add_ipv6ll_addr (self);
}
......
......@@ -231,8 +231,8 @@ _data_complete (NMNDiscDataInternal *data)
return &data->public;
}
static void
_emit_config_change (NMNDisc *self, NMNDiscConfigMap changed)
void
nm_ndisc_emit_config_change (NMNDisc *self, NMNDiscConfigMap changed)
{
_config_changed_log (self, changed);
g_signal_emit (self, signals[CONFIG_RECEIVED], 0,
......@@ -743,7 +743,7 @@ nm_ndisc_set_iid (NMNDisc *ndisc, const NMUtilsIPv6IfaceId iid)
if (rdata->addresses->len) {
_LOGD ("IPv6 interface identifier changed, flushing addresses");
g_array_remove_range (rdata->addresses, 0, rdata->addresses->len);
_emit_config_change (ndisc, NM_NDISC_CONFIG_ADDRESSES);
nm_ndisc_emit_config_change (ndisc, NM_NDISC_CONFIG_ADDRESSES);
solicit_routers (ndisc);
}
return TRUE;
......@@ -796,8 +796,8 @@ nm_ndisc_start (NMNDisc *ndisc)
}
}
void
nm_ndisc_dad_failed (NMNDisc *ndisc, const struct in6_addr *address)
NMNDiscConfigMap
nm_ndisc_dad_failed (NMNDisc *ndisc, const struct in6_addr *address, gboolean emit_changed_signal)
{
NMNDiscDataInternal *rdata;
guint i;
......@@ -819,8 +819,10 @@ nm_ndisc_dad_failed (NMNDisc *ndisc, const struct in6_addr *address)
i++;
}
if (changed)
_emit_config_change (ndisc, NM_NDISC_CONFIG_ADDRESSES);
if (emit_changed_signal && changed)
nm_ndisc_emit_config_change (ndisc, NM_NDISC_CONFIG_ADDRESSES);
return changed ? NM_NDISC_CONFIG_ADDRESSES : NM_NDISC_CONFIG_NONE;
}
#define CONFIG_MAP_MAX_STR 7
......@@ -1131,7 +1133,7 @@ check_timestamps (NMNDisc *ndisc, gint32 now, NMNDiscConfigMap changed)
clean_dns_domains (ndisc, now, &changed, &nextevent);
if (changed)
_emit_config_change (ndisc, changed);
nm_ndisc_emit_config_change (ndisc, changed);
if (nextevent != G_MAXINT32) {
if (nextevent <= now)
......
......@@ -100,6 +100,7 @@ typedef struct {
} NMNDiscDNSDomain;
typedef enum {
NM_NDISC_CONFIG_NONE = 0,
NM_NDISC_CONFIG_DHCP_LEVEL = 1 << 0,
NM_NDISC_CONFIG_GATEWAYS = 1 << 1,
NM_NDISC_CONFIG_ADDRESSES = 1 << 2,
......@@ -171,13 +172,17 @@ typedef struct {
GType nm_ndisc_get_type (void);
void nm_ndisc_emit_config_change (NMNDisc *self, NMNDiscConfigMap changed);
int nm_ndisc_get_ifindex (NMNDisc *self);
const char *nm_ndisc_get_ifname (NMNDisc *self);
NMNDiscNodeType nm_ndisc_get_node_type (NMNDisc *self);
gboolean nm_ndisc_set_iid (NMNDisc *ndisc, const NMUtilsIPv6IfaceId iid);
void nm_ndisc_start (NMNDisc *ndisc);
void nm_ndisc_dad_failed (NMNDisc *ndisc, const struct in6_addr *address);
NMNDiscConfigMap nm_ndisc_dad_failed (NMNDisc *ndisc,
const struct in6_addr *address,
gboolean emit_changed_signal);
void nm_ndisc_set_config (NMNDisc *ndisc,
const GArray *addresses,
const GArray *dns_servers,
......
......@@ -339,7 +339,8 @@ dad_failed_handle_idle (gpointer user_data)
if (nm_ndisc_dad_addr_is_fail_candidate (data->platform, obj)) {
nm_ndisc_dad_failed (data->ndisc,
&NMP_OBJECT_CAST_IP6_ADDRESS (obj)->address);
&NMP_OBJECT_CAST_IP6_ADDRESS (obj)->address,
TRUE);
}
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment