core/platform: sort routes before adding them in nm_platform_ipX_route_sync()

A gateway route can only be added, if there exists a device route
for that gateway. Therefore, nm_platform_ip4_route_sync() and
nm_platform_ip6_route_sync() has to add the device routes first,
before adding gateway routes.

Note: usually for all configured addresses, there is also a device
route for the subnet added by the kernel. This means, NM must first
configure the addresses before route_sync, so that these implicit device
routes already exist -- this is however already done correctly.

Signed-off-by: Thomas Haller <thaller@redhat.com>
This commit is contained in:
Thomas Haller
2014-01-23 09:11:19 +01:00
committed by Dan Williams
parent c8d7a06d64
commit 8959b6dbcb

View File

@@ -1607,7 +1607,7 @@ nm_platform_ip4_route_sync (int ifindex, const GArray *known_routes)
NMPlatformIP4Route *route; NMPlatformIP4Route *route;
const NMPlatformIP4Route *known_route; const NMPlatformIP4Route *known_route;
gboolean success; gboolean success;
int i; int i, i_type;
/* Delete unknown routes */ /* Delete unknown routes */
routes = nm_platform_ip4_route_get_all (ifindex, FALSE); routes = nm_platform_ip4_route_get_all (ifindex, FALSE);
@@ -1624,21 +1624,29 @@ nm_platform_ip4_route_sync (int ifindex, const GArray *known_routes)
} }
/* Add missing routes */ /* Add missing routes */
for (i = 0, success = TRUE; i < known_routes->len && success; i++) { for (i_type = 0, success = TRUE; i_type < 2 && success; i_type++) {
known_route = &g_array_index (known_routes, NMPlatformIP4Route, i); for (i = 0; i < known_routes->len && success; i++) {
known_route = &g_array_index (known_routes, NMPlatformIP4Route, i);
/* Ignore routes that already exist */ if ((known_route->gateway == 0) ^ (i_type != 0)) {
if (!array_contains_ip4_route (routes, known_route)) { /* Make two runs over the list of routes. On the first, only add
success = nm_platform_ip4_route_add (ifindex, * device routes, on the second the others (gateway routes). */
known_route->network, continue;
known_route->plen, }
known_route->gateway,
known_route->metric, /* Ignore routes that already exist */
known_route->mss); if (!array_contains_ip4_route (routes, known_route)) {
if (!success && known_route->source < NM_PLATFORM_SOURCE_USER) { success = nm_platform_ip4_route_add (ifindex,
nm_log_dbg (LOGD_PLATFORM, "ignore error adding IPv4 route to kernel: %s", known_route->network,
nm_platform_ip4_route_to_string (known_route)); known_route->plen,
success = TRUE; known_route->gateway,
known_route->metric,
known_route->mss);
if (!success && known_route->source < NM_PLATFORM_SOURCE_USER) {
nm_log_dbg (LOGD_PLATFORM, "ignore error adding IPv4 route to kernel: %s",
nm_platform_ip4_route_to_string (known_route));
success = TRUE;
}
} }
} }
} }
@@ -1665,7 +1673,7 @@ nm_platform_ip6_route_sync (int ifindex, const GArray *known_routes)
NMPlatformIP6Route *route; NMPlatformIP6Route *route;
const NMPlatformIP6Route *known_route; const NMPlatformIP6Route *known_route;
gboolean success; gboolean success;
int i; int i, i_type;
/* Delete unknown routes */ /* Delete unknown routes */
routes = nm_platform_ip6_route_get_all (ifindex, FALSE); routes = nm_platform_ip6_route_get_all (ifindex, FALSE);
@@ -1683,21 +1691,29 @@ nm_platform_ip6_route_sync (int ifindex, const GArray *known_routes)
} }
/* Add missing routes */ /* Add missing routes */
for (i = 0, success = TRUE; i < known_routes->len && success; i++) { for (i_type = 0, success = TRUE; i_type < 2 && success; i_type++) {
known_route = &g_array_index (known_routes, NMPlatformIP6Route, i); for (i = 0; i < known_routes->len && success; i++) {
known_route = &g_array_index (known_routes, NMPlatformIP6Route, i);
/* Ignore routes that already exist */ if (IN6_IS_ADDR_UNSPECIFIED (&known_route->gateway) ^ (i_type != 0)) {
if (!array_contains_ip6_route (routes, known_route)) { /* Make two runs over the list of routes. On the first, only add
success = nm_platform_ip6_route_add (ifindex, * device routes, on the second the others (gateway routes). */
known_route->network, continue;
known_route->plen, }
known_route->gateway,
known_route->metric, /* Ignore routes that already exist */
known_route->mss); if (!array_contains_ip6_route (routes, known_route)) {
if (!success && known_route->source < NM_PLATFORM_SOURCE_USER) { success = nm_platform_ip6_route_add (ifindex,
nm_log_dbg (LOGD_PLATFORM, "ignore error adding IPv6 route to kernel: %s", known_route->network,
nm_platform_ip6_route_to_string (known_route)); known_route->plen,
success = TRUE; known_route->gateway,
known_route->metric,
known_route->mss);
if (!success && known_route->source < NM_PLATFORM_SOURCE_USER) {
nm_log_dbg (LOGD_PLATFORM, "ignore error adding IPv6 route to kernel: %s",
nm_platform_ip6_route_to_string (known_route));
success = TRUE;
}
} }
} }
} }