summary refs log tree commit diff
path: root/src/nm-ip4-config.c
diff options
context:
space:
mode:
authorAron Xu <aron@debian.org>2016-12-20 20:06:37 +0800
committerAron Xu <aron@debian.org>2016-12-20 20:06:37 +0800
commit45cb5bb3c0e6edb887cf69b417fcaf7053814a9b (patch)
tree795f8d6a3aa1145e4ba8fa1564f39425ea0c6ed9 /src/nm-ip4-config.c
parent270c4830551c9810ad4e83f9a1db2b1cb946208c (diff)
Imported Upstream version 1.4.4 upstream/1.4.4
Diffstat (limited to 'src/nm-ip4-config.c')
-rw-r--r--src/nm-ip4-config.c128
1 files changed, 64 insertions, 64 deletions
diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c
index a4d43612..7b422359 100644
--- a/src/nm-ip4-config.c
+++ b/src/nm-ip4-config.c
@@ -55,6 +55,8 @@ typedef struct {
 	gint64 route_metric;
 	gboolean metered;
 	gint dns_priority;
+	GVariant *address_data_variant;
+	GVariant *addresses_variant;
 } NMIP4ConfigPrivate;
 
 struct _NMIP4Config {
@@ -207,8 +209,9 @@ _addresses_sort_cmp_get_prio (in_addr_t addr)
 static gint
 _addresses_sort_cmp (gconstpointer a, gconstpointer b)
 {
-	gint p1, p2, c;
+	gint p1, p2;
 	const NMPlatformIP4Address *a1 = a, *a2 = b;
+	guint32 n1, n2;
 
 	/* Sort by address type. For example link local will
 	 * be sorted *after* a global address. */
@@ -224,43 +227,30 @@ _addresses_sort_cmp (gconstpointer a, gconstpointer b)
 	if ((a1->label[0] == '\0') != (a2->label[0] == '\0'))
 		return (a1->label[0] == '\0') ? -1 : 1;
 
-	/* finally sort addresses lexically */
-	c = memcmp (&a1->address, &a2->address, sizeof (a2->address));
-	return c != 0 ? c : memcmp (a1, a2, sizeof (*a1));
-}
-
-gboolean
-nm_ip4_config_addresses_sort (NMIP4Config *self)
-{
-	NMIP4ConfigPrivate *priv;
-	size_t data_len = 0;
-	char *data_pre = NULL;
-	gboolean changed;
-
-	g_return_val_if_fail (NM_IS_IP4_CONFIG (self), FALSE);
+	/* Finally, sort addresses lexically. We compare only the
+	 * network part so that the order of addresses in the same
+	 * subnet (and thus also the primary/secondary role) is
+	 * preserved.
+	 */
+	n1 = a1->address & nm_utils_ip4_prefix_to_netmask (a1->plen);
+	n2 = a2->address & nm_utils_ip4_prefix_to_netmask (a2->plen);
 
-	priv = NM_IP4_CONFIG_GET_PRIVATE (self);
-	if (priv->addresses->len > 1) {
-		data_len = priv->addresses->len * g_array_get_element_size (priv->addresses);
-		data_pre = g_new (char, data_len);
-		memcpy (data_pre, priv->addresses->data, data_len);
+	return memcmp (&n1, &n2, sizeof (guint32));
+}
 
-		g_array_sort (priv->addresses, _addresses_sort_cmp);
+/*****************************************************************************/
 
-		changed = memcmp (data_pre, priv->addresses->data, data_len) != 0;
-		g_free (data_pre);
+static void
+notify_addresses (NMIP4Config *self)
+{
+	NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
 
-		if (changed) {
-			_notify (self, PROP_ADDRESS_DATA);
-			_notify (self, PROP_ADDRESSES);
-			return TRUE;
-		}
-	}
-	return FALSE;
+	nm_clear_g_variant (&priv->address_data_variant);
+	nm_clear_g_variant (&priv->addresses_variant);
+	_notify (self, PROP_ADDRESS_DATA);
+	_notify (self, PROP_ADDRESSES);
 }
 
-/*****************************************************************************/
-
 NMIP4Config *
 nm_ip4_config_capture (int ifindex, gboolean capture_resolv_conf)
 {
@@ -347,7 +337,6 @@ gboolean
 nm_ip4_config_commit (const NMIP4Config *config, int ifindex, gboolean routes_full_sync, gint64 default_route_metric)
 {
 	const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
-	int i;
 	gs_unref_ptrarray GPtrArray *added_addresses = NULL;
 
 	g_return_val_if_fail (ifindex > 0, FALSE);
@@ -359,7 +348,8 @@ nm_ip4_config_commit (const NMIP4Config *config, int ifindex, gboolean routes_fu
 
 	/* Routes */
 	{
-		int count = nm_ip4_config_get_num_routes (config);
+		guint i;
+		guint count = nm_ip4_config_get_num_routes (config);
 		GArray *routes = g_array_sized_new (FALSE, FALSE, sizeof (NMPlatformIP4Route), count);
 		gboolean success;
 		gs_unref_array GArray *device_route_purge_list = NULL;
@@ -1366,7 +1356,7 @@ gboolean
 nm_ip4_config_destination_is_direct (const NMIP4Config *config, guint32 network, guint8 plen)
 {
 	guint naddresses = nm_ip4_config_get_num_addresses (config);
-	int i;
+	guint i;
 	in_addr_t peer_network;
 
 	for (i = 0; i < naddresses; i++) {
@@ -1473,8 +1463,7 @@ nm_ip4_config_reset_addresses (NMIP4Config *config)
 
 	if (priv->addresses->len != 0) {
 		g_array_set_size (priv->addresses, 0);
-		_notify (config, PROP_ADDRESS_DATA);
-		_notify (config, PROP_ADDRESSES);
+		notify_addresses (config);
 	}
 }
 
@@ -1531,8 +1520,7 @@ nm_ip4_config_add_address (NMIP4Config *config, const NMPlatformIP4Address *new)
 
 	g_array_append_val (priv->addresses, *new);
 NOTIFY:
-	_notify (config, PROP_ADDRESS_DATA);
-	_notify (config, PROP_ADDRESSES);
+	notify_addresses (config);
 }
 
 void
@@ -1543,8 +1531,8 @@ nm_ip4_config_del_address (NMIP4Config *config, guint i)
 	g_return_if_fail (i < priv->addresses->len);
 
 	g_array_remove_index (priv->addresses, i);
-	_notify (config, PROP_ADDRESS_DATA);
-	_notify (config, PROP_ADDRESSES);
+
+	notify_addresses (config);
 }
 
 guint
@@ -1725,7 +1713,7 @@ nm_ip4_config_del_nameserver (NMIP4Config *config, guint i)
 	_notify (config, PROP_NAMESERVERS);
 }
 
-guint32
+guint
 nm_ip4_config_get_num_nameservers (const NMIP4Config *config)
 {
 	const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
@@ -1782,7 +1770,7 @@ nm_ip4_config_del_domain (NMIP4Config *config, guint i)
 	_notify (config, PROP_DOMAINS);
 }
 
-guint32
+guint
 nm_ip4_config_get_num_domains (const NMIP4Config *config)
 {
 	const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
@@ -1854,7 +1842,7 @@ nm_ip4_config_del_search (NMIP4Config *config, guint i)
 	_notify (config, PROP_SEARCHES);
 }
 
-guint32
+guint
 nm_ip4_config_get_num_searches (const NMIP4Config *config)
 {
 	const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
@@ -1911,7 +1899,7 @@ nm_ip4_config_del_dns_option(NMIP4Config *config, guint i)
 	_notify (config, PROP_DNS_OPTIONS);
 }
 
-guint32
+guint
 nm_ip4_config_get_num_dns_options (const NMIP4Config *config)
 {
 	const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
@@ -1999,7 +1987,7 @@ nm_ip4_config_del_nis_server (NMIP4Config *config, guint i)
 	g_array_remove_index (priv->nis, i);
 }
 
-guint32
+guint
 nm_ip4_config_get_num_nis_servers (const NMIP4Config *config)
 {
 	const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
@@ -2072,7 +2060,7 @@ nm_ip4_config_del_wins (NMIP4Config *config, guint i)
 	_notify (config, PROP_WINS_SERVERS);
 }
 
-guint32
+guint
 nm_ip4_config_get_num_wins (const NMIP4Config *config)
 {
 	const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
@@ -2147,7 +2135,7 @@ hash_u32 (GChecksum *sum, guint32 n)
 void
 nm_ip4_config_hash (const NMIP4Config *config, GChecksum *sum, gboolean dns_only)
 {
-	guint32 i;
+	guint i;
 	const char *s;
 
 	g_return_if_fail (config);
@@ -2267,6 +2255,8 @@ finalize (GObject *object)
 	NMIP4Config *self = NM_IP4_CONFIG (object);
 	NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
 
+	nm_clear_g_variant (&priv->address_data_variant);
+	nm_clear_g_variant (&priv->addresses_variant);
 	g_array_unref (priv->addresses);
 	g_array_unref (priv->routes);
 	g_array_unref (priv->nameservers);
@@ -2292,14 +2282,26 @@ get_property (GObject *object, guint prop_id,
 		g_value_set_int (value, priv->ifindex);
 		break;
 	case PROP_ADDRESS_DATA:
+	case PROP_ADDRESSES:
 		{
 			GVariantBuilder array_builder, addr_builder;
-			int naddr = nm_ip4_config_get_num_addresses (config);
-			int i;
+			gs_unref_array GArray *new = NULL;
+			guint naddr, i;
+
+			g_return_if_fail (!!priv->address_data_variant == !!priv->addresses_variant);
+
+			if (priv->address_data_variant)
+				goto return_cached;
 
+			naddr = nm_ip4_config_get_num_addresses (config);
+			new = g_array_sized_new (FALSE, FALSE, sizeof (NMPlatformIP4Address), naddr);
+			g_array_append_vals (new, priv->addresses->data, priv->addresses->len);
+			g_array_sort (new, _addresses_sort_cmp);
+
+			/* Build address data variant */
 			g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("aa{sv}"));
 			for (i = 0; i < naddr; i++) {
-				const NMPlatformIP4Address *address = nm_ip4_config_get_address (config, i);
+				const NMPlatformIP4Address *address = &g_array_index (new, NMPlatformIP4Address, i);
 
 				g_variant_builder_init (&addr_builder, G_VARIANT_TYPE ("a{sv}"));
 				g_variant_builder_add (&addr_builder, "{sv}",
@@ -2322,19 +2324,12 @@ get_property (GObject *object, guint prop_id,
 
 				g_variant_builder_add (&array_builder, "a{sv}", &addr_builder);
 			}
+			priv->address_data_variant = g_variant_ref_sink (g_variant_builder_end (&array_builder));
 
-			g_value_take_variant (value, g_variant_builder_end (&array_builder));
-		}
-		break;
-	case PROP_ADDRESSES:
-		{
-			GVariantBuilder array_builder;
-			int naddr = nm_ip4_config_get_num_addresses (config);
-			int i;
-
+			/* Build addresses variant */
 			g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("aau"));
 			for (i = 0; i < naddr; i++) {
-				const NMPlatformIP4Address *address = nm_ip4_config_get_address (config, i);
+				const NMPlatformIP4Address *address = &g_array_index (new, NMPlatformIP4Address, i);
 				guint32 dbus_addr[3];
 
 				dbus_addr[0] = address->address;
@@ -2345,15 +2340,20 @@ get_property (GObject *object, guint prop_id,
 				                       g_variant_new_fixed_array (G_VARIANT_TYPE_UINT32,
 				                                                  dbus_addr, 3, sizeof (guint32)));
 			}
+			priv->addresses_variant = g_variant_ref_sink (g_variant_builder_end (&array_builder));
 
-			g_value_take_variant (value, g_variant_builder_end (&array_builder));
+return_cached:
+			g_value_set_variant (value,
+			                     prop_id == PROP_ADDRESS_DATA ?
+			                     priv->address_data_variant :
+			                     priv->addresses_variant);
 		}
 		break;
 	case PROP_ROUTE_DATA:
 		{
 			GVariantBuilder array_builder, route_builder;
 			guint nroutes = nm_ip4_config_get_num_routes (config);
-			int i;
+			guint i;
 
 			g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("aa{sv}"));
 			for (i = 0; i < nroutes; i++) {
@@ -2385,7 +2385,7 @@ get_property (GObject *object, guint prop_id,
 		{
 			GVariantBuilder array_builder;
 			guint nroutes = nm_ip4_config_get_num_routes (config);
-			int i;
+			guint i;
 
 			g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("aau"));
 			for (i = 0; i < nroutes; i++) {