summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBeniamino Galvani <bgalvani@redhat.com>2016-11-18 11:48:12 +0100
committerBeniamino Galvani <bgalvani@redhat.com>2016-12-05 10:56:51 +0100
commite02752c2ed6a8dde884021817a5da8fc101330db (patch)
tree535c6fd307f35625fd9cd25a261cae0a152e2817
parent593cfc73c1d263e330748d686ead61f7451f166c (diff)
downloadNetworkManager-e02752c2ed6a8dde884021817a5da8fc101330db.tar.gz
ip4-config: don't change order of addresses in the same subnet
When multiple address are assigned to an interface and the kernel must decide which one should be used to communicate with a given IP, it chooses the most specific one in the same subnet as the destination. In case there are multiple addresses in the same subnet, the primary address is choosen, which is basically the first one that was added. With commit 719742513705 ("device: expose NMIP4Config:addresses in stable/defined sort order") we sorted all the addresses before committing the configuration, with the side effect that the order no longer respected the one in the user configuration. Instead, change the sort function to keep the subnet order unchanged.
-rw-r--r--src/nm-ip4-config.c15
1 files changed, 11 insertions, 4 deletions
diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c
index a78dc3af37..f7441dc0a2 100644
--- a/src/nm-ip4-config.c
+++ b/src/nm-ip4-config.c
@@ -207,8 +207,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,9 +225,15 @@ _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));
+ /* 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);
+
+ return memcmp (&n1, &n2, sizeof (guint32));
}
gboolean