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 7197425137 ("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.
This commit is contained in:
Beniamino Galvani
2016-11-18 11:48:12 +01:00
parent 593cfc73c1
commit e02752c2ed

View File

@@ -207,8 +207,9 @@ _addresses_sort_cmp_get_prio (in_addr_t addr)
static gint static gint
_addresses_sort_cmp (gconstpointer a, gconstpointer b) _addresses_sort_cmp (gconstpointer a, gconstpointer b)
{ {
gint p1, p2, c; gint p1, p2;
const NMPlatformIP4Address *a1 = a, *a2 = b; const NMPlatformIP4Address *a1 = a, *a2 = b;
guint32 n1, n2;
/* Sort by address type. For example link local will /* Sort by address type. For example link local will
* be sorted *after* a global address. */ * 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')) if ((a1->label[0] == '\0') != (a2->label[0] == '\0'))
return (a1->label[0] == '\0') ? -1 : 1; return (a1->label[0] == '\0') ? -1 : 1;
/* finally sort addresses lexically */ /* Finally, sort addresses lexically. We compare only the
c = memcmp (&a1->address, &a2->address, sizeof (a2->address)); * network part so that the order of addresses in the same
return c != 0 ? c : memcmp (a1, a2, sizeof (*a1)); * 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 gboolean