summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2017-07-11 16:38:49 +0200
committerThomas Haller <thaller@redhat.com>2017-07-16 16:37:15 +0200
commit0f3715f9a83dcfb4e589f98c76afcab4dd89aced (patch)
tree3b214c9692083bf018ec70982f21e1f0a0f8ad3b
parent46ae651e45b91506cbae8b3195c4d251b8a7328b (diff)
downloadNetworkManager-0f3715f9a83dcfb4e589f98c76afcab4dd89aced.tar.gz
platform: pass full route object to platform delete function
Contrary to addresses, routes have no ID. When deleting a route, you cannot just specify certain properties like network/plen,metric. Well, actually you can specify only certain properties, but then kernel will treat unspecified properties as wildcard and delete the first matching route. That is not something we want, because we need to be in control which exact route shall be deleted. Also, rtm_tos *must* match. Even if we like the wildcard behavior, we would need to pass TOS to nm_platform_ip4_route_delete() to be able to delete routes with non-zero TOS. So, while certain properties may be omitted, some must not. See how test_ip4_route_options() was broken. For NetworkManager it only makes ever sense to call delete on a route, if the route is already fully known. Which means, we only delete routes that we have already in the platform cache (otherwise, how would we know that there is something to delete). Because of that, no longer have separate IPv4 and IPv6 functions. Instead, have nm_platform_ip_route_delete() which accepts a full NMPObject from the platform cache. The code in core doesn't jet make use of this new functionality. It will in the future. At least, it fixes deleting routes with differing TOS.
-rw-r--r--src/nm-default-route-manager.c2
-rw-r--r--src/nm-route-manager.c47
-rw-r--r--src/platform/nm-fake-platform.c82
-rw-r--r--src/platform/nm-linux-platform.c150
-rw-r--r--src/platform/nm-platform.c62
-rw-r--r--src/platform/nm-platform.h9
-rw-r--r--src/platform/tests/test-common.c54
-rw-r--r--src/platform/tests/test-common.h3
-rw-r--r--src/platform/tests/test-route.c36
9 files changed, 208 insertions, 237 deletions
diff --git a/src/nm-default-route-manager.c b/src/nm-default-route-manager.c
index f6362bccf6..fc209fc852 100644
--- a/src/nm-default-route-manager.c
+++ b/src/nm-default-route-manager.c
@@ -371,7 +371,7 @@ _platform_route_sync_flush (const VTableIP *vtable, NMDefaultRouteManager *self,
*/
if ( !entry
&& (has_ifindex_synced || ifindex_to_flush == route->ifindex)) {
- vtable->vt->route_delete_default (priv->platform, route->ifindex, route->metric);
+ nm_platform_ip_route_delete (priv->platform, NMP_OBJECT_UP_CAST (route));
changed = TRUE;
}
}
diff --git a/src/nm-route-manager.c b/src/nm-route-manager.c
index bcf911f12e..a54deebe47 100644
--- a/src/nm-route-manager.c
+++ b/src/nm-route-manager.c
@@ -58,7 +58,8 @@ typedef struct {
NMRouteManager *self;
gint64 scheduled_at_ns;
guint idle_id;
- NMPObject *obj;
+ const NMPObject *obj;
+ const NMPObject *obj_cached;
} IP4DeviceRoutePurgeEntry;
/*****************************************************************************/
@@ -490,8 +491,10 @@ _get_next_plat_route (const RouteIndex *index, gboolean start_at_zero, guint *cu
++*cur_idx;
/* get next route from the platform index. */
- if (*cur_idx < index->len)
+ if (*cur_idx < index->len) {
+ nm_assert (NMP_OBJECT_UP_CAST (index->entries[*cur_idx]));
return index->entries[*cur_idx];
+ }
*cur_idx = index->len;
return NULL;
}
@@ -649,7 +652,8 @@ _vx_route_sync (const VTableIP *vtable, NMRouteManager *self, int ifindex, const
* in platform. Delete it. */
_LOGt (vtable->vt->addr_family, "%3d: platform rt-rm #%u - %s", ifindex, i_plat_routes,
vtable->vt->route_to_string (cur_plat_route, NULL, 0));
- vtable->vt->route_delete (priv->platform, ifindex, cur_plat_route);
+ nm_assert (ifindex == cur_plat_route->rx.ifindex);
+ nm_platform_ip_route_delete (priv->platform, NMP_OBJECT_UP_CAST (cur_plat_route));
}
}
}
@@ -796,7 +800,7 @@ next:
while (cur_plat_route) {
int route_dest_cmp_result = 0;
- g_assert (cur_plat_route->rx.ifindex == ifindex);
+ nm_assert (cur_plat_route->rx.ifindex == ifindex);
_LOGt (vtable->vt->addr_family, "%3d: platform rt #%u - %s", ifindex, i_plat_routes, vtable->vt->route_to_string (cur_plat_route, NULL, 0));
@@ -816,8 +820,10 @@ next:
/* if @cur_ipx_route is not equal to @plat_route, the route must be deleted. */
if ( !cur_ipx_route
|| route_dest_cmp_result != 0
- || *p_effective_metric != cur_plat_route->rx.metric)
- vtable->vt->route_delete (priv->platform, ifindex, cur_plat_route);
+ || *p_effective_metric != cur_plat_route->rx.metric) {
+ nm_assert (ifindex == cur_plat_route->rx.ifindex);
+ nm_platform_ip_route_delete (priv->platform, NMP_OBJECT_UP_CAST (cur_plat_route));
+ }
cur_plat_route = _get_next_plat_route (plat_routes_idx, FALSE, &i_plat_routes);
}
@@ -1074,6 +1080,7 @@ _ip4_device_routes_purge_entry_create (NMRouteManager *self, const NMPlatformIP4
entry->scheduled_at_ns = now_ns;
entry->idle_id = 0;
entry->obj = nmp_object_new (NMP_OBJECT_TYPE_IP4_ROUTE, (NMPlatformObject *) route);
+ entry->obj_cached = NULL;
return entry;
}
@@ -1081,6 +1088,7 @@ static void
_ip4_device_routes_purge_entry_free (IP4DeviceRoutePurgeEntry *entry)
{
nmp_object_unref (entry->obj);
+ nmp_object_unref (entry->obj_cached);
nm_clear_g_source (&entry->idle_id);
g_slice_free (IP4DeviceRoutePurgeEntry, entry);
}
@@ -1100,13 +1108,9 @@ _ip4_device_routes_idle_cb (IP4DeviceRoutePurgeEntry *entry)
return G_SOURCE_REMOVE;
}
- _LOGt (vtable_v4.vt->addr_family, "device-route: delete %s", nmp_object_to_string (entry->obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0));
+ _LOGt (vtable_v4.vt->addr_family, "device-route: delete %s", nmp_object_to_string (entry->obj_cached, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0));
- nm_platform_ip4_route_delete (priv->platform,
- entry->obj->ip4_route.ifindex,
- entry->obj->ip4_route.network,
- entry->obj->ip4_route.plen,
- entry->obj->ip4_route.metric);
+ nm_platform_ip_route_delete (priv->platform, entry->obj_cached);
g_hash_table_remove (priv->ip4_device_routes.entries, entry->obj);
_ip4_device_routes_cancel (self);
@@ -1123,12 +1127,9 @@ _ip4_device_routes_ip4_route_changed (NMPlatform *platform,
{
const NMPlatformSignalChangeType change_type = change_type_i;
NMRouteManagerPrivate *priv;
- NMPObject obj_needle;
+ const NMPObject *obj;
IP4DeviceRoutePurgeEntry *entry;
- if (change_type == NM_PLATFORM_SIGNAL_REMOVED)
- return;
-
if ( route->rt_source != NM_IP_CONFIG_SOURCE_RTPROT_KERNEL
|| route->metric != 0) {
/* we don't have an automatically created device route at hand. Bail out early. */
@@ -1137,8 +1138,9 @@ _ip4_device_routes_ip4_route_changed (NMPlatform *platform,
priv = NM_ROUTE_MANAGER_GET_PRIVATE (self);
- entry = g_hash_table_lookup (priv->ip4_device_routes.entries,
- nmp_object_stackinit (&obj_needle, NMP_OBJECT_TYPE_IP4_ROUTE, (NMPlatformObject *) route));
+ obj = NMP_OBJECT_UP_CAST (route);
+
+ entry = g_hash_table_lookup (priv->ip4_device_routes.entries, obj);
if (!entry)
return;
@@ -1149,6 +1151,15 @@ _ip4_device_routes_ip4_route_changed (NMPlatform *platform,
return;
}
+ entry->obj_cached = nmp_object_unref (entry->obj_cached);
+
+ if (change_type == NM_PLATFORM_SIGNAL_REMOVED) {
+ if (nm_clear_g_source (&entry->idle_id))
+ _LOGt (vtable_v4.vt->addr_family, "device-route: unschedule %s", nmp_object_to_string (entry->obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0));
+ return;
+ }
+
+ entry->obj_cached = nmp_object_ref (obj);
if (entry->idle_id == 0) {
_LOGt (vtable_v4.vt->addr_family, "device-route: schedule %s", nmp_object_to_string (entry->obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0));
entry->idle_id = g_idle_add ((GSourceFunc) _ip4_device_routes_idle_cb, entry);
diff --git a/src/platform/nm-fake-platform.c b/src/platform/nm-fake-platform.c
index 718ee974ae..f817bfb571 100644
--- a/src/platform/nm-fake-platform.c
+++ b/src/platform/nm-fake-platform.c
@@ -106,9 +106,7 @@ static gboolean ipx_address_delete (NMPlatform *platform,
static gboolean ipx_route_delete (NMPlatform *platform,
int addr_family,
int ifindex,
- gconstpointer network,
- const guint8 *plen,
- const guint32 *metric);
+ const NMPObject *obj);
static gboolean ip6_address_add (NMPlatform *platform,
int ifindex,
@@ -401,8 +399,8 @@ link_delete (NMPlatform *platform, int ifindex)
/* Remove addresses and routes which belong to the deleted interface */
ipx_address_delete (platform, AF_INET, ifindex, NULL, NULL, NULL);
ipx_address_delete (platform, AF_INET6, ifindex, NULL, NULL, NULL);
- ipx_route_delete (platform, AF_INET, ifindex, NULL, NULL, NULL);
- ipx_route_delete (platform, AF_INET6, ifindex, NULL, NULL, NULL);
+ ipx_route_delete (platform, AF_INET, ifindex, NULL);
+ ipx_route_delete (platform, AF_INET6, ifindex, NULL);
nm_platform_cache_update_emit_signal (platform,
cache_op,
@@ -1115,42 +1113,54 @@ static gboolean
ipx_route_delete (NMPlatform *platform,
int addr_family,
int ifindex,
- gconstpointer network,
- const guint8 *plen,
- const guint32 *metric)
+ const NMPObject *obj)
{
gs_unref_ptrarray GPtrArray *objs = g_ptr_array_new_with_free_func ((GDestroyNotify) nmp_object_unref);
NMDedupMultiIter iter;
const NMPObject *o = NULL;
guint i;
-
- g_assert (NM_IN_SET (addr_family, AF_INET, AF_INET6));
+ NMPObjectType obj_type;
+
+ if (addr_family == AF_UNSPEC) {
+ g_assert (NM_IN_SET (NMP_OBJECT_GET_TYPE (obj), NMP_OBJECT_TYPE_IP4_ROUTE,
+ NMP_OBJECT_TYPE_IP6_ROUTE));
+ g_assert (ifindex == -1);
+ ifindex = obj->object.ifindex;
+ obj_type = NMP_OBJECT_GET_TYPE (obj);
+ } else {
+ g_assert (NM_IN_SET (addr_family, AF_INET, AF_INET6));
+ g_assert (!obj);
+ g_assert (ifindex > 0);
+ obj_type = addr_family == AF_INET
+ ? NMP_OBJECT_TYPE_IP4_ROUTE
+ : NMP_OBJECT_TYPE_IP6_ROUTE;
+ }
nmp_cache_iter_for_each (&iter,
nm_platform_lookup_addrroute (platform,
- addr_family == AF_INET
- ? NMP_OBJECT_TYPE_IP4_ROUTE
- : NMP_OBJECT_TYPE_IP6_ROUTE,
- 0),
+ obj_type,
+ ifindex),
&o) {
const NMPObject *obj_old = NULL;
- if (addr_family == AF_INET) {
- const NMPlatformIP4Route *route = NMP_OBJECT_CAST_IP4_ROUTE (o);
+ if (obj) {
+ if (obj_type == NMP_OBJECT_TYPE_IP4_ROUTE) {
+ const NMPlatformIP4Route *route = NMP_OBJECT_CAST_IP4_ROUTE (o);
+ const NMPlatformIP4Route *r = NMP_OBJECT_CAST_IP4_ROUTE (obj);
- if ( route->ifindex != ifindex
- || (network && route->network != *((guint32 *) network))
- || (plen && route->plen != *plen)
- || (metric && route->metric != *metric))
- continue;
- } else {
- const NMPlatformIP6Route *route = NMP_OBJECT_CAST_IP6_ROUTE (o);
+ if ( route->network != r->network
+ || route->plen != r->plen
+ || route->metric != r->metric)
+ continue;
+ } else {
+ const NMPlatformIP6Route *route = NMP_OBJECT_CAST_IP6_ROUTE (o);
+ const NMPlatformIP6Route *r = NMP_OBJECT_CAST_IP6_ROUTE (obj);
- if ( route->ifindex != ifindex
- || (network && !IN6_ARE_ADDR_EQUAL (&route->network, network))
- || (plen && route->plen != *plen)
- || (metric && route->metric != *metric))
- continue;
+ if ( !IN6_ARE_ADDR_EQUAL (&route->network, &r->network)
+ || route->plen != r->plen
+ || route->metric != r->metric)
+ continue;
+ }
}
if (nmp_cache_remove (nm_platform_get_cache (platform),
@@ -1172,16 +1182,13 @@ ipx_route_delete (NMPlatform *platform,
}
static gboolean
-ip4_route_delete (NMPlatform *platform, int ifindex, in_addr_t network, guint8 plen, guint32 metric)
+ip_route_delete (NMPlatform *platform, const NMPObject *obj)
{
- return ipx_route_delete (platform, AF_INET, ifindex, &network, &plen, &metric);
-}
+ g_assert (NM_IS_FAKE_PLATFORM (platform));
+ g_assert (NM_IN_SET (NMP_OBJECT_GET_TYPE (obj), NMP_OBJECT_TYPE_IP4_ROUTE,
+ NMP_OBJECT_TYPE_IP6_ROUTE));
-static gboolean
-ip6_route_delete (NMPlatform *platform, int ifindex, struct in6_addr network, guint8 plen, guint32 metric)
-{
- metric = nm_utils_ip6_route_metric_normalize (metric);
- return ipx_route_delete (platform, AF_INET6, ifindex, &network, &plen, &metric);
+ return ipx_route_delete (platform, AF_UNSPEC, -1, obj);
}
static gboolean
@@ -1391,6 +1398,5 @@ nm_fake_platform_class_init (NMFakePlatformClass *klass)
platform_class->ip4_route_add = ip4_route_add;
platform_class->ip6_route_add = ip6_route_add;
- platform_class->ip4_route_delete = ip4_route_delete;
- platform_class->ip6_route_delete = ip6_route_delete;
+ platform_class->ip_route_delete = ip_route_delete;
}
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
index fc2491066c..e25091aa9a 100644
--- a/src/platform/nm-linux-platform.c
+++ b/src/platform/nm-linux-platform.c
@@ -2418,19 +2418,14 @@ nla_put_failure:
static struct nl_msg *
_nl_msg_new_route (int nlmsg_type,
int nlmsg_flags,
- int family,
- int ifindex,
+ const NMPObject *obj,
NMIPConfigSource source,
unsigned char scope,
- gconstpointer network,
- guint8 plen,
gconstpointer gateway,
- guint32 metric,
guint32 mss,
gconstpointer pref_src,
gconstpointer src,
guint8 src_plen,
- guint8 tos,
guint32 window,
guint32 cwnd,
guint32 initcwnd,
@@ -2439,23 +2434,24 @@ _nl_msg_new_route (int nlmsg_type,
guint32 lock)
{
struct nl_msg *msg;
+ const NMPClass *klass = NMP_OBJECT_GET_CLASS (obj);
+ gboolean is_v4 = klass->addr_family == AF_INET;
struct rtmsg rtmsg = {
- .rtm_family = family,
- .rtm_tos = tos,
+ .rtm_family = klass->addr_family,
+ .rtm_tos = obj->ip_route.tos,
.rtm_table = RT_TABLE_MAIN, /* omit setting RTA_TABLE attribute */
.rtm_protocol = nmp_utils_ip_config_source_coerce_to_rtprot (source),
.rtm_scope = scope,
.rtm_type = RTN_UNICAST,
.rtm_flags = 0,
- .rtm_dst_len = plen,
+ .rtm_dst_len = obj->ip_route.plen,
.rtm_src_len = src ? src_plen : 0,
};
gsize addr_len;
- nm_assert (NM_IN_SET (family, AF_INET, AF_INET6));
+ nm_assert (NM_IN_SET (NMP_OBJECT_GET_TYPE (obj), NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE));
nm_assert (NM_IN_SET (nlmsg_type, RTM_NEWROUTE, RTM_DELROUTE));
- nm_assert (network);
msg = nlmsg_alloc_simple (nlmsg_type, nlmsg_flags);
if (!msg)
@@ -2464,14 +2460,19 @@ _nl_msg_new_route (int nlmsg_type,
if (nlmsg_append (msg, &rtmsg, sizeof (rtmsg), NLMSG_ALIGNTO) < 0)
goto nla_put_failure;
- addr_len = family == AF_INET ? sizeof (in_addr_t) : sizeof (struct in6_addr);
+ addr_len = is_v4
+ ? sizeof (in_addr_t)
+ : sizeof (struct in6_addr);
- NLA_PUT (msg, RTA_DST, addr_len, network);
+ NLA_PUT (msg, RTA_DST, addr_len,
+ is_v4
+ ? (gconstpointer) &obj->ip4_route.network
+ : (gconstpointer) &obj->ip6_route.network);
if (src)
NLA_PUT (msg, RTA_SRC, addr_len, src);
- NLA_PUT_U32 (msg, RTA_PRIORITY, metric);
+ NLA_PUT_U32 (msg, RTA_PRIORITY, obj->ip_route.metric);
if (pref_src)
NLA_PUT (msg, RTA_PREFSRC, addr_len, pref_src);
@@ -2505,7 +2506,7 @@ _nl_msg_new_route (int nlmsg_type,
if ( gateway
&& memcmp (gateway, &nm_ip_addr_zero, addr_len) != 0)
NLA_PUT (msg, RTA_GATEWAY, addr_len, gateway);
- NLA_PUT_U32 (msg, RTA_OIF, ifindex);
+ NLA_PUT_U32 (msg, RTA_OIF, obj->ip_route.ifindex);
return msg;
@@ -5688,86 +5689,78 @@ ip_route_get_lock_flag (NMPlatformIPRoute *route)
static gboolean
ip4_route_add (NMPlatform *platform, const NMPlatformIP4Route *route)
{
- NMPObject obj_id;
+ NMPObject obj;
+ NMPlatformIP4Route *r;
nm_auto_nlmsg struct nl_msg *nlmsg = NULL;
- in_addr_t network;
- network = nm_utils_ip4_address_clear_host_address (route->network, route->plen);
+ nmp_object_stackinit (&obj, NMP_OBJECT_TYPE_IP4_ROUTE, (const NMPlatformObject *) route);
+ r = NMP_OBJECT_CAST_IP4_ROUTE (&obj);
+ r->network = nm_utils_ip4_address_clear_host_address (r->network, r->plen);
- /* FIXME: take the scope from route into account */
nlmsg = _nl_msg_new_route (RTM_NEWROUTE,
NLM_F_CREATE | NLM_F_REPLACE,
- AF_INET,
- route->ifindex,
+ &obj,
route->rt_source,
route->gateway ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK,
- &network,
- route->plen,
&route->gateway,
- route->metric,
route->mss,
route->pref_src ? &route->pref_src : NULL,
NULL,
0,
- route->tos,
route->window,
route->cwnd,
route->initcwnd,
route->initrwnd,
route->mtu,
ip_route_get_lock_flag ((NMPlatformIPRoute *) route));
-
- nmp_object_stackinit_id_ip4_route (&obj_id, route->ifindex, network, route->plen, route->metric);
- return do_add_addrroute (platform, &obj_id, nlmsg);
+ return do_add_addrroute (platform, &obj, nlmsg);
}
static gboolean
ip6_route_add (NMPlatform *platform, const NMPlatformIP6Route *route)
{
- NMPObject obj_id;
+ NMPObject obj;
+ NMPlatformIP6Route *r;
nm_auto_nlmsg struct nl_msg *nlmsg = NULL;
- struct in6_addr network;
- nm_utils_ip6_address_clear_host_address (&network, &route->network, route->plen);
+ nmp_object_stackinit (&obj, NMP_OBJECT_TYPE_IP6_ROUTE, (const NMPlatformObject *) route);
+ r = NMP_OBJECT_CAST_IP6_ROUTE (&obj);
+ nm_utils_ip6_address_clear_host_address (&r->network, &r->network, r->plen);
- /* FIXME: take the scope from route into account */
nlmsg = _nl_msg_new_route (RTM_NEWROUTE,
NLM_F_CREATE | NLM_F_REPLACE,
- AF_INET6,
- route->ifindex,
+ &obj,
route->rt_source,
IN6_IS_ADDR_UNSPECIFIED (&route->gateway) ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSE,
- &network,
- route->plen,
&route->gateway,
- route->metric,
route->mss,
!IN6_IS_ADDR_UNSPECIFIED (&route->pref_src) ? &route->pref_src : NULL,
!IN6_IS_ADDR_UNSPECIFIED (&route->src) ? &route->src : NULL,
route->src_plen,
- route->tos,
route->window,
route->cwnd,
route->initcwnd,
route->initrwnd,
route->mtu,
ip_route_get_lock_flag ((NMPlatformIPRoute *) route));
-
- nmp_object_stackinit_id_ip6_route (&obj_id, route->ifindex, &network, route->plen, route->metric);
- return do_add_addrroute (platform, &obj_id, nlmsg);
+ return do_add_addrroute (platform, &obj, nlmsg);
}
static gboolean
-ip4_route_delete (NMPlatform *platform, int ifindex, in_addr_t network, guint8 plen, guint32 metric)
+ip_route_delete (NMPlatform *platform,
+ const NMPObject *obj)
{
+ nm_auto_nmpobj const NMPObject *obj_keep_alive = NULL;
nm_auto_nlmsg struct nl_msg *nlmsg = NULL;
- NMPObject obj_id;
- network = nm_utils_ip4_address_clear_host_address (network, plen);
+ nm_assert (NM_IN_SET (NMP_OBJECT_GET_TYPE (obj), NMP_OBJECT_TYPE_IP4_ROUTE,
+ NMP_OBJECT_TYPE_IP6_ROUTE));
- nmp_object_stackinit_id_ip4_route (&obj_id, ifindex, network, plen, metric);
+ if (!NMP_OBJECT_IS_STACKINIT (obj))
+ obj_keep_alive = nmp_object_ref (obj);
- if (metric == 0) {
+ if ( NMP_OBJECT_GET_TYPE (obj) == NMP_OBJECT_TYPE_IP4_ROUTE
+ && obj->ip_route.metric == 0) {
NMPCache *cache = nm_platform_get_cache (platform);
/* Deleting an IPv4 route with metric 0 does not only delete an exectly matching route.
@@ -5776,9 +5769,12 @@ ip4_route_delete (NMPlatform *platform, int ifindex, in_addr_t network, guint8 p
*
* Instead, make sure that we have the most recent state and process all
* delayed actions (including re-reading data from netlink). */
+
+ /* FIXME: later, we only want to pass in here @obj instances that originate
+ * from the cache, and where we know that the route with metric 0 exists. */
delayed_action_handle_all (platform, TRUE);
- if (!nmp_cache_lookup_obj (cache, &obj_id)) {
+ if (!nmp_cache_lookup_obj (cache, obj)) {
/* hmm... we are about to delete an IP4 route with metric 0. We must only
* send the delete request if such a route really exists. Above we refreshed
* the platform cache, still no such route exists.
@@ -5786,65 +5782,20 @@ ip4_route_delete (NMPlatform *platform, int ifindex, in_addr_t network, guint8 p
* Be extra careful and reload the routes. We must be sure that such a
* route doesn't exists, because when we add an IPv4 address, we immediately
* afterwards try to delete the kernel-added device route with metric 0.
- * It might be, that we didn't yet get the notification about that route.
- *
- * FIXME: once our ip4_address_add() is sure that upon return we have
- * the latest state from in the platform cache, we might save this
- * additional expensive cache-resync. */
+ * It might be, that we didn't yet get the notification about that route. */
do_request_one_type (platform, NMP_OBJECT_TYPE_IP4_ROUTE);
- if (!nmp_cache_lookup_obj (cache, &obj_id))
+ if (!nmp_cache_lookup_obj (cache, obj))
return TRUE;
}
}
nlmsg = _nl_msg_new_route (RTM_DELROUTE,
0,
- AF_INET,
- ifindex,
- NM_IP_CONFIG_SOURCE_UNKNOWN,
- RT_SCOPE_NOWHERE,
- &network,
- plen,
- NULL,
- metric,
- 0,
- NULL,
- NULL,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0);
- if (!nlmsg)
- return FALSE;
-
- return do_delete_object (platform, &obj_id, nlmsg);
-}
-
-static gboolean
-ip6_route_delete (NMPlatform *platform, int ifindex, struct in6_addr network, guint8 plen, guint32 metric)
-{
- nm_auto_nlmsg struct nl_msg *nlmsg = NULL;
- NMPObject obj_id;
-
- metric = nm_utils_ip6_route_metric_normalize (metric);
-
- nm_utils_ip6_address_clear_host_address (&network, &network, plen);
-
- nlmsg = _nl_msg_new_route (RTM_DELROUTE,
- 0,
- AF_INET6,
- ifindex,
+ obj,
NM_IP_CONFIG_SOURCE_UNKNOWN,
RT_SCOPE_NOWHERE,
- &network,
- plen,
NULL,
- metric,
0,
NULL,
NULL,
@@ -5854,14 +5805,10 @@ ip6_route_delete (NMPlatform *platform, int ifindex, struct in6_addr network, gu
0,
0,
0,
- 0,
0);
if (!nlmsg)
return FALSE;
-
- nmp_object_stackinit_id_ip6_route (&obj_id, ifindex, &network, plen, metric);
-
- return do_delete_object (platform, &obj_id, nlmsg);
+ return do_delete_object (platform, obj, nlmsg);
}
/*****************************************************************************/
@@ -6593,8 +6540,7 @@ nm_linux_platform_class_init (NMLinuxPlatformClass *klass)
platform_class->ip4_route_add = ip4_route_add;
platform_class->ip6_route_add = ip6_route_add;
- platform_class->ip4_route_delete = ip4_route_delete;
- platform_class->ip6_route_delete = ip6_route_delete;
+ platform_class->ip_route_delete = ip_route_delete;
platform_class->check_support_kernel_extended_ifa_flags = check_support_kernel_extended_ifa_flags;
platform_class->check_support_user_ipv6ll = check_support_user_ipv6ll;
diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c
index 57a4eb860f..bd9015b551 100644
--- a/src/platform/nm-platform.c
+++ b/src/platform/nm-platform.c
@@ -3446,29 +3446,19 @@ nm_platform_ip6_route_add (NMPlatform *self, const NMPlatformIP6Route *route)
}
gboolean
-nm_platform_ip4_route_delete (NMPlatform *self, int ifindex, in_addr_t network, guint8 plen, guint32 metric)
+nm_platform_ip_route_delete (NMPlatform *self,
+ const NMPObject *obj)
{
- char str_dev[TO_STRING_DEV_BUF_SIZE];
-
_CHECK_SELF (self, klass, FALSE);
- _LOGD ("route: deleting IPv4 route %s/%d, metric=%"G_GUINT32_FORMAT", ifindex %d%s",
- nm_utils_inet4_ntop (network, NULL), plen, metric, ifindex,
- _to_string_dev (self, ifindex, str_dev, sizeof (str_dev)));
- return klass->ip4_route_delete (self, ifindex, network, plen, metric);
-}
-
-gboolean
-nm_platform_ip6_route_delete (NMPlatform *self, int ifindex, struct in6_addr network, guint8 plen, guint32 metric)
-{
- char str_dev[TO_STRING_DEV_BUF_SIZE];
+ nm_assert (NM_IN_SET (NMP_OBJECT_GET_TYPE (obj), NMP_OBJECT_TYPE_IP4_ROUTE,
+ NMP_OBJECT_TYPE_IP6_ROUTE));
- _CHECK_SELF (self, klass, FALSE);
+ _LOGD ("route: deleting IPv%c route %s",
+ NMP_OBJECT_GET_TYPE (obj) == NMP_OBJECT_TYPE_IP4_ROUTE ? '4' : '6',
+ nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0));
- _LOGD ("route: deleting IPv6 route %s/%d, metric=%"G_GUINT32_FORMAT", ifindex %d%s",
- nm_utils_inet6_ntop (&network, NULL), plen, metric, ifindex,
- _to_string_dev (self, ifindex, str_dev, sizeof (str_dev)));
- return klass->ip6_route_delete (self, ifindex, network, plen, metric);
+ return klass->ip_route_delete (self, obj);
}
const NMPlatformIP4Route *
@@ -5160,44 +5150,12 @@ _vtr_v6_route_add (NMPlatform *self, int ifindex, const NMPlatformIPXRoute *rout
return nm_platform_ip6_route_add (self, &rt);
}
-static gboolean
-_vtr_v4_route_delete (NMPlatform *self, int ifindex, const NMPlatformIPXRoute *route)
-{
- return nm_platform_ip4_route_delete (self,
- ifindex > 0 ? ifindex : route->rx.ifindex,
- route->r4.network,
- route->rx.plen,
- route->rx.metric);
-}
-
-static gboolean
-_vtr_v6_route_delete (NMPlatform *self, int ifindex, const NMPlatformIPXRoute *route)
-{
- return nm_platform_ip6_route_delete (self,
- ifindex > 0 ? ifindex : route->rx.ifindex,
- route->r6.network,
- route->rx.plen,
- route->rx.metric);
-}
-
static guint32
_vtr_v4_metric_normalize (guint32 metric)
{
return metric;
}
-static gboolean
-_vtr_v4_route_delete_default (NMPlatform *self, int ifindex, guint32 metric)
-{
- return nm_platform_ip4_route_delete (self, ifindex, 0, 0, metric);
-}
-
-static gboolean
-_vtr_v6_route_delete_default (NMPlatform *self, int ifindex, guint32 metric)
-{
- return nm_platform_ip6_route_delete (self, ifindex, in6addr_any, 0, metric);
-}
-
/*****************************************************************************/
const NMPlatformVTableRoute nm_platform_vtable_route_v4 = {
@@ -5208,8 +5166,6 @@ const NMPlatformVTableRoute nm_platform_vtable_route_v4 = {
.route_cmp = (int (*) (const NMPlatformIPXRoute *a, const NMPlatformIPXRoute *b, gboolean consider_host_part)) nm_platform_ip4_route_cmp_full,
.route_to_string = (const char *(*) (const NMPlatformIPXRoute *route, char *buf, gsize len)) nm_platform_ip4_route_to_string,
.route_add = _vtr_v4_route_add,
- .route_delete = _vtr_v4_route_delete,
- .route_delete_default = _vtr_v4_route_delete_default,
.metric_normalize = _vtr_v4_metric_normalize,
};
@@ -5221,8 +5177,6 @@ const NMPlatformVTableRoute nm_platform_vtable_route_v6 = {
.route_cmp = (int (*) (const NMPlatformIPXRoute *a, const NMPlatformIPXRoute *b, gboolean consider_host_part)) nm_platform_ip6_route_cmp_full,
.route_to_string = (const char *(*) (const NMPlatformIPXRoute *route, char *buf, gsize len)) nm_platform_ip6_route_to_string,
.route_add = _vtr_v6_route_add,
- .route_delete = _vtr_v6_route_delete,
- .route_delete_default = _vtr_v6_route_delete_default,
.metric_normalize = nm_utils_ip6_route_metric_normalize,
};
diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h
index 8ff6d5eda8..956e718223 100644
--- a/src/platform/nm-platform.h
+++ b/src/platform/nm-platform.h
@@ -367,8 +367,6 @@ typedef struct {
int (*route_cmp) (const NMPlatformIPXRoute *a, const NMPlatformIPXRoute *b, gboolean consider_host_part);
const char *(*route_to_string) (const NMPlatformIPXRoute *route, char *buf, gsize len);
gboolean (*route_add) (NMPlatform *self, int ifindex, const NMPlatformIPXRoute *route, gint64 metric);
- gboolean (*route_delete) (NMPlatform *self, int ifindex, const NMPlatformIPXRoute *route);
- gboolean (*route_delete_default) (NMPlatform *self, int ifindex, guint32 metric);
guint32 (*metric_normalize) (guint32 metric);
} NMPlatformVTableRoute;
@@ -644,8 +642,7 @@ typedef struct {
gboolean (*ip4_route_add) (NMPlatform *, const NMPlatformIP4Route *route);
gboolean (*ip6_route_add) (NMPlatform *, const NMPlatformIP6Route *route);
- gboolean (*ip4_route_delete) (NMPlatform *, int ifindex, in_addr_t network, guint8 plen, guint32 metric);
- gboolean (*ip6_route_delete) (NMPlatform *, int ifindex, struct in6_addr network, guint8 plen, guint32 metric);
+ gboolean (*ip_route_delete) (NMPlatform *, const NMPObject *obj);
gboolean (*check_support_kernel_extended_ifa_flags) (NMPlatform *);
gboolean (*check_support_user_ipv6ll) (NMPlatform *);
@@ -931,6 +928,7 @@ NMPlatformError nm_platform_link_sit_add (NMPlatform *self,
const NMPlatformLink **out_link);
const NMPlatformIP6Address *nm_platform_ip6_address_get (NMPlatform *self, int ifindex, struct in6_addr address);
+
gboolean nm_platform_ip4_address_add (NMPlatform *self,
int ifindex,
in_addr_t address,
@@ -958,8 +956,7 @@ const NMPlatformIP4Route *nm_platform_ip4_route_get (NMPlatform *self, int ifind
const NMPlatformIP6Route *nm_platform_ip6_route_get (NMPlatform *self, int ifindex, struct in6_addr network, guint8 plen, guint32 metric);
gboolean nm_platform_ip4_route_add (NMPlatform *self, const NMPlatformIP4Route *route);
gboolean nm_platform_ip6_route_add (NMPlatform *self, const NMPlatformIP6Route *route);
-gboolean nm_platform_ip4_route_delete (NMPlatform *self, int ifindex, in_addr_t network, guint8 plen, guint32 metric);
-gboolean nm_platform_ip6_route_delete (NMPlatform *self, int ifindex, struct in6_addr network, guint8 plen, guint32 metric);
+gboolean nm_platform_ip_route_delete (NMPlatform *self, const NMPObject *route);
const char *nm_platform_link_to_string (const NMPlatformLink *link, char *buf, gsize len);
const char *nm_platform_lnk_gre_to_string (const NMPlatformLnkGre *lnk, char *buf, gsize len);
diff --git a/src/platform/tests/test-common.c b/src/platform/tests/test-common.c
index 10753f1f08..51234cf17a 100644
--- a/src/platform/tests/test-common.c
+++ b/src/platform/tests/test-common.c
@@ -100,6 +100,60 @@ nmtstp_platform_ip6_address_get_all (NMPlatform *self, int ifindex)
/*****************************************************************************/
+gboolean
+nmtstp_platform_ip4_route_delete (NMPlatform *platform, int ifindex, in_addr_t network, guint8 plen, guint32 metric)
+{
+ NMDedupMultiIter iter;
+
+ nm_platform_process_events (platform);
+
+ nm_dedup_multi_iter_for_each (&iter,
+ nm_platform_lookup_addrroute (platform,
+ NMP_OBJECT_TYPE_IP4_ROUTE,
+ ifindex)) {
+ const NMPlatformIP4Route *r = NMP_OBJECT_CAST_IP4_ROUTE (iter.current->obj);
+
+ if ( r->ifindex != ifindex
+ || r->network != network
+ || r->plen != plen
+ || r->metric != metric) {
+ continue;
+ }
+
+ return nm_platform_ip_route_delete (platform, NMP_OBJECT_UP_CAST (r));
+ }
+
+ return TRUE;
+}
+
+gboolean
+nmtstp_platform_ip6_route_delete (NMPlatform *platform, int ifindex, struct in6_addr network, guint8 plen, guint32 metric)
+{
+ NMDedupMultiIter iter;
+
+ nm_platform_process_events (platform);
+
+ nm_dedup_multi_iter_for_each (&iter,
+ nm_platform_lookup_addrroute (platform,
+ NMP_OBJECT_TYPE_IP6_ROUTE,
+ ifindex)) {
+ const NMPlatformIP6Route *r = NMP_OBJECT_CAST_IP6_ROUTE (iter.current->obj);
+
+ if ( r->ifindex != ifindex
+ || !IN6_ARE_ADDR_EQUAL (&r->network, &network)
+ || r->plen != plen
+ || r->metric != metric) {
+ continue;
+ }
+
+ return nm_platform_ip_route_delete (platform, NMP_OBJECT_UP_CAST (r));
+ }
+
+ return TRUE;
+}
+
+/*****************************************************************************/
+
SignalData *
add_signal_full (const char *name, NMPlatformSignalChangeType change_type, GCallback callback, int ifindex, const char *ifname)
{
diff --git a/src/platform/tests/test-common.h b/src/platform/tests/test-common.h
index 9cef6f358d..4d65a26683 100644
--- a/src/platform/tests/test-common.h
+++ b/src/platform/tests/test-common.h
@@ -217,6 +217,9 @@ nmtstp_ip6_route_get_all (NMPlatform *platform,
GArray *nmtstp_platform_ip4_address_get_all (NMPlatform *self, int ifindex);
GArray *nmtstp_platform_ip6_address_get_all (NMPlatform *self, int ifindex);
+gboolean nmtstp_platform_ip4_route_delete (NMPlatform *platform, int ifindex, in_addr_t network, guint8 plen, guint32 metric);
+gboolean nmtstp_platform_ip6_route_delete (NMPlatform *platform, int ifindex, struct in6_addr network, guint8 plen, guint32 metric);
+
const NMPlatformLink *nmtstp_link_get_typed (NMPlatform *platform, int ifindex, const char *name, NMLinkType link_type);
const NMPlatformLink *nmtstp_link_get (NMPlatform *platform, int ifindex, const char *name);
diff --git a/src/platform/tests/test-route.c b/src/platform/tests/test-route.c
index 18fe75f90b..adaf7e538a 100644
--- a/src/platform/tests/test-route.c
+++ b/src/platform/tests/test-route.c
@@ -136,7 +136,7 @@ test_ip4_route_metric0 (void)
nmtstp_assert_ip4_route_exists (NULL, TRUE, DEVICE_NAME, network, plen, metric);
/* Deleting route with metric 0 does nothing */
- g_assert (nm_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, plen, 0));
+ g_assert (nmtstp_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, plen, 0));
ensure_no_signal (route_removed);
nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, network, plen, 0);
@@ -150,21 +150,21 @@ test_ip4_route_metric0 (void)
nmtstp_assert_ip4_route_exists (NULL, TRUE, DEVICE_NAME, network, plen, metric);
/* Delete route with metric 0 */
- g_assert (nm_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, plen, 0));
+ g_assert (nmtstp_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, plen, 0));
accept_signal (route_removed);
nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, network, plen, 0);
nmtstp_assert_ip4_route_exists (NULL, TRUE, DEVICE_NAME, network, plen, metric);
/* Delete route with metric 0 again (we expect nothing to happen) */
- g_assert (nm_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, plen, 0));
+ g_assert (nmtstp_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, plen, 0));
ensure_no_signal (route_removed);
nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, network, plen, 0);
nmtstp_assert_ip4_route_exists (NULL, TRUE, DEVICE_NAME, network, plen, metric);
/* Delete the other route */
- g_assert (nm_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, plen, metric));
+ g_assert (nmtstp_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, plen, metric));
accept_signal (route_removed);
nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, network, plen, 0);
@@ -250,19 +250,19 @@ test_ip4_route (void)
g_ptr_array_unref (routes);
/* Remove route */
- g_assert (nm_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, plen, metric));
+ g_assert (nmtstp_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, plen, metric));
nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, network, plen, metric);
accept_signal (route_removed);
/* Remove route again */
- g_assert (nm_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, plen, metric));
+ g_assert (nmtstp_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, plen, metric));
/* Remove default route */
- g_assert (nm_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, 0, 0, metric));
+ g_assert (nmtstp_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, 0, 0, metric));
accept_signal (route_removed);
/* Remove route to gateway */
- g_assert (nm_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, gateway, 32, metric));
+ g_assert (nmtstp_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, gateway, 32, metric));
accept_signal (route_removed);
free_signal (route_added);
@@ -352,19 +352,19 @@ test_ip6_route (void)
g_ptr_array_unref (routes);
/* Remove route */
- g_assert (nm_platform_ip6_route_delete (NM_PLATFORM_GET, ifindex, network, plen, metric));
+ g_assert (nmtstp_platform_ip6_route_delete (NM_PLATFORM_GET, ifindex, network, plen, metric));
g_assert (!nm_platform_ip6_route_get (NM_PLATFORM_GET, ifindex, network, plen, metric));
accept_signal (route_removed);
/* Remove route again */
- g_assert (nm_platform_ip6_route_delete (NM_PLATFORM_GET, ifindex, network, plen, metric));
+ g_assert (nmtstp_platform_ip6_route_delete (NM_PLATFORM_GET, ifindex, network, plen, metric));
/* Remove default route */
- g_assert (nm_platform_ip6_route_delete (NM_PLATFORM_GET, ifindex, in6addr_any, 0, metric));
+ g_assert (nmtstp_platform_ip6_route_delete (NM_PLATFORM_GET, ifindex, in6addr_any, 0, metric));
accept_signal (route_removed);
/* Remove route to gateway */
- g_assert (nm_platform_ip6_route_delete (NM_PLATFORM_GET, ifindex, gateway, 128, metric));
+ g_assert (nmtstp_platform_ip6_route_delete (NM_PLATFORM_GET, ifindex, gateway, 128, metric));
accept_signal (route_removed);
free_signal (route_added);
@@ -438,11 +438,11 @@ test_ip4_route_options (void)
rts[0].lock_cwnd = TRUE;
g_assert_cmpint (routes->len, ==, 1);
nmtst_platform_ip4_routes_equal_aptr ((const NMPObject *const*) routes->pdata, rts, routes->len, TRUE);
- g_ptr_array_unref (routes);
/* Remove route */
- /*FIXME */
- //g_assert (nm_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, 24, 20));
+ g_assert (nm_platform_ip_route_delete (NM_PLATFORM_GET, routes->pdata[0]));
+
+ g_ptr_array_unref (routes);
}
@@ -537,9 +537,9 @@ test_ip6_route_options (gconstpointer test_data)
g_ptr_array_unref (routes);
for (i = 0; i < rts_n; i++) {
- g_assert (nm_platform_ip6_route_delete (NM_PLATFORM_GET, IFINDEX,
- rts_add[i].network, rts_add[i].plen,
- rts_add[i].metric));
+ g_assert (nmtstp_platform_ip6_route_delete (NM_PLATFORM_GET, IFINDEX,
+ rts_add[i].network, rts_add[i].plen,
+ rts_add[i].metric));
}
for (i = 0; i < addr_n; i++) {