summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2017-07-04 12:49:47 +0200
committerThomas Haller <thaller@redhat.com>2017-07-05 18:37:39 +0200
commitac60b0ce60c8f3535f9b46f31db0fb0b1e4b67ea (patch)
treef10e3165eb828764c94d6efe79cd85ad267d52db
parent71cf60e852dc04df22b1c127fef00138e6d3a115 (diff)
downloadNetworkManager-ac60b0ce60c8f3535f9b46f31db0fb0b1e4b67ea.tar.gz
platform: move link accessors to NMPlatform base class
and refactor NMFakePlatform to also track links via NMPCache. For one, now NMFakePlatform also tests NMPCache, increasing the coverage of what we care about. Also, all our NMPlatform implementations now use NMPObject and NMPCache. That means, we can expose those as part of the public API. Which is great, because callers can keep a reference to the NMPObject object and make use of generic functions like nmp_object_to_string().
-rw-r--r--src/platform/nm-fake-platform.c679
-rw-r--r--src/platform/nm-linux-platform.c179
-rw-r--r--src/platform/nm-platform.c158
-rw-r--r--src/platform/nm-platform.h12
-rw-r--r--src/platform/nmp-object.c23
-rw-r--r--src/platform/nmp-object.h18
-rw-r--r--src/platform/tests/test-link.c7
7 files changed, 538 insertions, 538 deletions
diff --git a/src/platform/nm-fake-platform.c b/src/platform/nm-fake-platform.c
index 96475a9a2f..718ee974ae 100644
--- a/src/platform/nm-fake-platform.c
+++ b/src/platform/nm-fake-platform.c
@@ -40,10 +40,8 @@
/*****************************************************************************/
typedef struct {
- NMPlatformLink link;
-
+ const NMPObject *obj;
char *udi;
- NMPObject *lnk;
struct in6_addr ip6_lladdr;
} NMFakePlatformLink;
@@ -93,7 +91,10 @@ G_DEFINE_TYPE (NMFakePlatform, nm_fake_platform, NM_TYPE_PLATFORM)
/*****************************************************************************/
-static void link_changed (NMPlatform *platform, NMFakePlatformLink *device, gboolean raise_signal);
+static void link_changed (NMPlatform *platform,
+ NMFakePlatformLink *device,
+ NMPCacheOpsType cache_op,
+ const NMPObject *obj_old);
static gboolean ipx_address_delete (NMPlatform *platform,
int addr_family,
@@ -161,165 +162,126 @@ sysctl_get (NMPlatform *platform, const char *pathid, int dirfd, const char *pat
return g_strdup (g_hash_table_lookup (priv->options, path));
}
-static const char *
-type_to_type_name (NMLinkType type)
-{
- switch (type) {
- case NM_LINK_TYPE_UNKNOWN:
- return "unknown";
- case NM_LINK_TYPE_LOOPBACK:
- return "loopback";
- case NM_LINK_TYPE_ETHERNET:
- return "ethernet";
- case NM_LINK_TYPE_DUMMY:
- return "dummy";
- case NM_LINK_TYPE_BRIDGE:
- return "bridge";
- case NM_LINK_TYPE_BOND:
- return "bond";
- case NM_LINK_TYPE_TEAM:
- return "team";
- case NM_LINK_TYPE_VLAN:
- return "vlan";
- case NM_LINK_TYPE_NONE:
- default:
- return NULL;
- }
-}
-
-static void
-link_init (NMFakePlatformLink *device, int ifindex, int type, const char *name)
-{
- gs_free char *ip6_lladdr = NULL;
-
- g_assert (!name || strlen (name) < sizeof(device->link.name));
-
- memset (device, 0, sizeof (*device));
-
- ip6_lladdr = ifindex > 0 ? g_strdup_printf ("fe80::fa1e:%0x:%0x", ifindex / 256, ifindex % 256) : NULL;
-
- device->link.ifindex = name ? ifindex : 0;
- device->link.type = type;
- device->link.kind = type_to_type_name (type);
- device->link.driver = type_to_type_name (type);
- device->udi = g_strdup_printf ("fake:%d", ifindex);
- device->link.initialized = TRUE;
- device->ip6_lladdr = *nmtst_inet6_from_string (ip6_lladdr);
- if (name)
- strcpy (device->link.name, name);
- switch (device->link.type) {
- case NM_LINK_TYPE_DUMMY:
- device->link.n_ifi_flags = NM_FLAGS_SET (device->link.n_ifi_flags, IFF_NOARP);
- break;
- default:
- device->link.n_ifi_flags = NM_FLAGS_UNSET (device->link.n_ifi_flags, IFF_NOARP);
- break;
- }
-}
-
static NMFakePlatformLink *
link_get (NMPlatform *platform, int ifindex)
{
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE ((NMFakePlatform *) platform);
NMFakePlatformLink *device;
+ int idx;
+
+ if (ifindex <= 0)
+ g_return_val_if_reached (NULL);
- if (ifindex >= priv->links->len)
+ idx = ifindex - 1;
+ if (idx >= priv->links->len)
goto not_found;
- device = &g_array_index (priv->links, NMFakePlatformLink, ifindex);
- if (!device->link.ifindex)
+
+ device = &g_array_index (priv->links, NMFakePlatformLink, idx);
+ if (!device->obj)
goto not_found;
+ g_assert (ifindex == NMP_OBJECT_CAST_LINK (device->obj)->ifindex);
+ g_assert (device->obj == nm_platform_link_get_obj (platform, ifindex, FALSE));
+
return device;
not_found:
_LOGD ("link not found: %d", ifindex);
return NULL;
}
-static GArray *
-link_get_all (NMPlatform *platform)
+static void
+link_add_prepare (NMPlatform *platform,
+ NMFakePlatformLink *device,
+ NMPObject *obj_tmp)
{
- NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE ((NMFakePlatform *) platform);
- GArray *links = g_array_sized_new (TRUE, TRUE, sizeof (NMPlatformLink), priv->links->len);
- int i;
+ gboolean connected;
- for (i = 0; i < priv->links->len; i++)
- if (g_array_index (priv->links, NMFakePlatformLink, i).link.ifindex)
- g_array_append_val (links, g_array_index (priv->links, NMFakePlatformLink, i).link);
-
- return links;
-}
+ /* we must clear the driver, because platform cache want's to set it */
+ g_assert (obj_tmp->link.driver == g_intern_string (obj_tmp->link.driver));
+ obj_tmp->link.driver = NULL;
-static const NMPlatformLink *
-_nm_platform_link_get (NMPlatform *platform, int ifindex)
-{
- NMFakePlatformLink *device = link_get (platform, ifindex);
+ if (NM_IN_SET (obj_tmp->link.type, NM_LINK_TYPE_BRIDGE,
+ NM_LINK_TYPE_BOND)) {
+ connected = FALSE;
+ if (NM_FLAGS_HAS (obj_tmp->link.n_ifi_flags, IFF_UP)) {
+ NMPLookup lookup;
+ NMDedupMultiIter iter;
+ const NMPObject *slave_candidate = NULL;
+
+ nmp_cache_iter_for_each (&iter,
+ nmp_cache_lookup (nm_platform_get_cache (platform),
+ nmp_lookup_init_obj_type (&lookup,
+ NMP_OBJECT_TYPE_LINK)),
+ &slave_candidate) {
+ if (nmp_cache_link_connected_for_slave (obj_tmp->link.ifindex, slave_candidate)) {
+ connected = TRUE;
+ break;
+ }
+ }
+ }
+ } else
+ connected = NM_FLAGS_HAS (obj_tmp->link.n_ifi_flags, IFF_UP);
- return device ? &device->link : NULL;
+ obj_tmp->link.n_ifi_flags = NM_FLAGS_ASSIGN (obj_tmp->link.n_ifi_flags, IFF_LOWER_UP, connected);
+ obj_tmp->link.connected = connected;
}
-static const NMPlatformLink *
-_nm_platform_link_get_by_ifname (NMPlatform *platform, const char *ifname)
+static NMFakePlatformLink *
+link_add_pre (NMPlatform *platform,
+ const char *name,
+ NMLinkType type,
+ const void *address,
+ size_t address_len)
{
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE ((NMFakePlatform *) platform);
- guint i;
+ NMFakePlatformLink *device;
+ int ifindex;
+ NMPObject *o;
+ NMPlatformLink *link;
+ gs_free char *ip6_lladdr = NULL;
- for (i = 0; i < priv->links->len; i++) {
- NMFakePlatformLink *device = &g_array_index (priv->links, NMFakePlatformLink, i);
+ g_assert (!name || strlen (name) < IFNAMSIZ);
- if (!strcmp (device->link.name, ifname))
- return &device->link;
- }
- return NULL;
-}
+ g_array_set_size (priv->links, priv->links->len + 1);
+ device = &g_array_index (priv->links, NMFakePlatformLink, priv->links->len - 1);
+ ifindex = priv->links->len;
-static const NMPlatformLink *
-_nm_platform_link_get_by_address (NMPlatform *platform,
- gconstpointer address,
- size_t length)
-{
- NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE ((NMFakePlatform *) platform);
- guint i;
+ memset (device, 0, sizeof (*device));
- if ( length == 0
- || length > NM_UTILS_HWADDR_LEN_MAX
- || !address)
- g_return_val_if_reached (NULL);
+ o = nmp_object_new_link (ifindex);
+ link = NMP_OBJECT_CAST_LINK (o);
- for (i = 0; i < priv->links->len; i++) {
- NMFakePlatformLink *device = &g_array_index (priv->links, NMFakePlatformLink, i);
+ ip6_lladdr = ifindex > 0 ? g_strdup_printf ("fe80::fa1e:%0x:%0x", ifindex / 256, ifindex % 256) : NULL;
- if ( device->link.addr.len == length
- && memcmp (device->link.addr.data, address, length) == 0) {
- return &device->link;
- }
+ link->ifindex = name ? ifindex : 0;
+ link->type = type;
+ link->kind = g_intern_string (nm_link_type_to_string (type));
+ link->initialized = TRUE;
+ if (name)
+ strcpy (link->name, name);
+ switch (link->type) {
+ case NM_LINK_TYPE_DUMMY:
+ link->n_ifi_flags = NM_FLAGS_SET (link->n_ifi_flags, IFF_NOARP);
+ break;
+ default:
+ link->n_ifi_flags = NM_FLAGS_UNSET (link->n_ifi_flags, IFF_NOARP);
+ break;
}
- return NULL;
-}
-static const NMPObject *
-link_get_lnk (NMPlatform *platform,
- int ifindex,
- NMLinkType link_type,
- const NMPlatformLink **out_link)
-{
- NMFakePlatformLink *device = link_get (platform, ifindex);
-
- if (!device)
- return NULL;
-
- NM_SET_OUT (out_link, &device->link);
-
- if (!device->lnk)
- return NULL;
+ o->_link.netlink.is_in_netlink = TRUE;
- if (link_type == NM_LINK_TYPE_NONE)
- return device->lnk;
+ if (address) {
+ g_assert (address_len > 0 && address_len <= sizeof (link->addr.data));
+ memcpy (link->addr.data, address, address_len);
+ link->addr.len = address_len;
+ } else
+ g_assert (address_len == 0);
- if ( link_type != device->link.type
- || link_type != NMP_OBJECT_GET_CLASS (device->lnk)->lnk_link_type)
- return NULL;
+ device->obj = o;
+ device->udi = g_strdup_printf ("fake:%d", ifindex);
+ device->ip6_lladdr = *nmtst_inet6_from_string (ip6_lladdr);
- return device->lnk;
+ return device;
}
static gboolean
@@ -331,113 +293,201 @@ link_add (NMPlatform *platform,
size_t address_len,
const NMPlatformLink **out_link)
{
- NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE ((NMFakePlatform *) platform);
- NMFakePlatformLink device;
- NMFakePlatformLink device_veth = { };
- NMFakePlatformLink *new_device;
-
- link_init (&device, priv->links->len, type, name);
-
- if (address) {
- g_return_val_if_fail (address_len > 0 && address_len <= sizeof (device.link.addr.data), FALSE);
- memcpy (device.link.addr.data, address, address_len);
- device.link.addr.len = address_len;
- }
+ NMFakePlatformLink *device;
+ NMFakePlatformLink *device_veth = NULL;
+ nm_auto_nmpobj const NMPObject *obj_old = NULL;
+ nm_auto_nmpobj const NMPObject *obj_new = NULL;
+ nm_auto_nmpobj const NMPObject *obj_old_veth = NULL;
+ nm_auto_nmpobj const NMPObject *obj_new_veth = NULL;
+ NMPCacheOpsType cache_op;
+ NMPCacheOpsType cache_op_veth = NMP_CACHE_OPS_UNCHANGED;
- g_array_append_val (priv->links, device);
- new_device = &g_array_index (priv->links, NMFakePlatformLink, priv->links->len - 1);
+ device = link_add_pre (platform, name, type, address, address_len);
if (veth_peer) {
- link_init (&device_veth, priv->links->len, type, veth_peer);
- g_array_append_val (priv->links, device_veth);
- new_device = &g_array_index (priv->links, NMFakePlatformLink, priv->links->len - 2);
+ g_assert (type == NM_LINK_TYPE_VETH);
+ device_veth = link_add_pre (platform, veth_peer, type, NULL, 0);
} else
g_assert (type != NM_LINK_TYPE_VETH);
+ link_add_prepare (platform, device, (NMPObject *) device->obj);
+ cache_op = nmp_cache_update_netlink (nm_platform_get_cache (platform),
+ (NMPObject *) device->obj,
+ &obj_old, &obj_new);
+ g_assert (cache_op == NMP_CACHE_OPS_ADDED);
+ nmp_object_unref (device->obj);
+ device->obj = nmp_object_ref (obj_new);
+ if (veth_peer) {
+ link_add_prepare (platform, device_veth, (NMPObject *) device_veth->obj);
+ cache_op_veth = nmp_cache_update_netlink (nm_platform_get_cache (platform),
+ (NMPObject *) device_veth->obj,
+ &obj_old_veth, &obj_new_veth);
+ g_assert (cache_op == NMP_CACHE_OPS_ADDED);
+ nmp_object_unref (device->obj);
+ device->obj = nmp_object_ref (obj_new);
+ }
if (out_link)
- *out_link = &new_device->link;
+ *out_link = NMP_OBJECT_CAST_LINK (device->obj);
- if (device.link.ifindex) {
- g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_LINK_CHANGED, (int) NMP_OBJECT_TYPE_LINK, device.link.ifindex, &device, (int) NM_PLATFORM_SIGNAL_ADDED);
+ link_changed (platform, device, cache_op, NULL);
+ if (veth_peer)
+ link_changed (platform, device_veth, cache_op_veth, NULL);
- link_changed (platform, new_device, FALSE);
- }
+ return TRUE;
+}
- if (veth_peer) {
- g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_LINK_CHANGED, (int) NMP_OBJECT_TYPE_LINK, device_veth.link.ifindex, &device_veth, (int) NM_PLATFORM_SIGNAL_ADDED);
+static NMFakePlatformLink *
+link_add_one (NMPlatform *platform,
+ const char *name,
+ NMLinkType link_type,
+ void (*prepare_fcn) (NMPlatform *platform, NMFakePlatformLink *device, gconstpointer user_data),
+ gconstpointer user_data,
+ const NMPlatformLink **out_link)
+{
+ NMFakePlatformLink *device;
+ nm_auto_nmpobj const NMPObject *obj_old = NULL;
+ nm_auto_nmpobj const NMPObject *obj_new = NULL;
+ NMPCacheOpsType cache_op;
+ int ifindex;
- link_changed (platform, &g_array_index (priv->links, NMFakePlatformLink, priv->links->len - 1), FALSE);
- }
+ device = link_add_pre (platform, name, NM_LINK_TYPE_VLAN, NULL, 0);
- return TRUE;
+ ifindex = NMP_OBJECT_CAST_LINK (device->obj)->ifindex;
+
+ if (prepare_fcn)
+ prepare_fcn (platform, device, user_data);
+
+ link_add_prepare (platform, device, (NMPObject *) device->obj);
+ cache_op = nmp_cache_update_netlink (nm_platform_get_cache (platform),
+ (NMPObject *) device->obj,
+ &obj_old, &obj_new);
+ g_assert (cache_op == NMP_CACHE_OPS_ADDED);
+ nmp_object_unref (device->obj);
+ device->obj = nmp_object_ref (obj_new);
+
+ link_changed (platform, device, cache_op, obj_old);
+
+ device = link_get (platform, ifindex);
+ if (!device)
+ g_assert_not_reached ();
+
+ NM_SET_OUT (out_link, NMP_OBJECT_CAST_LINK (device->obj));
+ return device;
}
static gboolean
link_delete (NMPlatform *platform, int ifindex)
{
NMFakePlatformLink *device = link_get (platform, ifindex);
- NMPlatformLink deleted_device;
+ nm_auto_nmpobj const NMPObject *obj_old = NULL;
+ nm_auto_nmpobj const NMPObject *obj_old2 = NULL;
+ NMPCacheOpsType cache_op;
- if (!device || !device->link.ifindex)
+ if (!device)
return FALSE;
- memcpy (&deleted_device, &device->link, sizeof (deleted_device));
- memset (&device->link, 0, sizeof (device->link));
- g_clear_pointer (&device->lnk, nmp_object_unref);
+ obj_old = g_steal_pointer (&device->obj);
g_clear_pointer (&device->udi, g_free);
+ cache_op = nmp_cache_remove (nm_platform_get_cache (platform),
+ obj_old,
+ FALSE,
+ &obj_old2);
+ g_assert (cache_op == NMP_CACHE_OPS_REMOVED);
+ g_assert (obj_old2);
+ g_assert (obj_old == obj_old2);
+
/* 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);
- g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_LINK_CHANGED, (int) NMP_OBJECT_TYPE_LINK, ifindex, &deleted_device, (int) NM_PLATFORM_SIGNAL_REMOVED);
-
+ nm_platform_cache_update_emit_signal (platform,
+ cache_op,
+ obj_old2,
+ NULL);
return TRUE;
}
-static const char *
-link_get_type_name (NMPlatform *platform, int ifindex)
+static void
+link_set_obj (NMPlatform *platform,
+ NMFakePlatformLink *device,
+ NMPObject *obj_tmp)
{
- return type_to_type_name (nm_platform_link_get_type (platform, ifindex));
+ nm_auto_nmpobj const NMPObject *obj_new = NULL;
+ nm_auto_nmpobj const NMPObject *obj_old = NULL;
+ nm_auto_nmpobj NMPObject *obj_tmp_tmp = NULL;
+ NMPCacheOpsType cache_op;
+
+ g_assert (device);
+ g_assert (NMP_OBJECT_GET_TYPE (device->obj) == NMP_OBJECT_TYPE_LINK);
+
+ if (!obj_tmp) {
+ obj_tmp_tmp = nmp_object_clone (device->obj, FALSE);
+ obj_tmp = obj_tmp_tmp;
+ }
+
+ g_assert (NMP_OBJECT_GET_TYPE (obj_tmp) == NMP_OBJECT_TYPE_LINK);
+
+ link_add_prepare (platform, device, obj_tmp);
+ cache_op = nmp_cache_update_netlink (nm_platform_get_cache (platform),
+ obj_tmp, &obj_old, &obj_new);
+ g_assert (NM_IN_SET (cache_op, NMP_CACHE_OPS_UNCHANGED,
+ NMP_CACHE_OPS_UPDATED));
+ g_assert (obj_old == device->obj);
+ g_assert (obj_new);
+
+ nmp_object_unref (device->obj);
+ device->obj = nmp_object_ref (obj_new);
+
+ link_changed (platform, device, cache_op, obj_old);
}
static void
-link_changed (NMPlatform *platform, NMFakePlatformLink *device, gboolean raise_signal)
+link_set_flags (NMPlatform *platform,
+ NMFakePlatformLink *device,
+ guint n_ifi_flags)
{
- NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE ((NMFakePlatform *) platform);
- int i;
+ nm_auto_nmpobj NMPObject *obj_tmp = NULL;
- if (raise_signal)
- g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_LINK_CHANGED, (int) NMP_OBJECT_TYPE_LINK, device->link.ifindex, &device->link, (int) NM_PLATFORM_SIGNAL_CHANGED);
+ g_assert (device);
+ g_assert (NMP_OBJECT_GET_TYPE (device->obj) == NMP_OBJECT_TYPE_LINK);
- if (device->link.ifindex && !IN6_IS_ADDR_UNSPECIFIED (&device->ip6_lladdr)) {
- if (device->link.connected)
- ip6_address_add (platform, device->link.ifindex, in6addr_any, 64, device->ip6_lladdr, NM_PLATFORM_LIFETIME_PERMANENT, NM_PLATFORM_LIFETIME_PERMANENT, 0);
- else
- ip6_address_delete (platform, device->link.ifindex, device->ip6_lladdr, 64);
- }
+ obj_tmp = nmp_object_clone (device->obj, FALSE);
+ obj_tmp->link.n_ifi_flags = n_ifi_flags;
+ link_set_obj (platform, device, obj_tmp);
+}
- if (device->link.master) {
- gboolean connected = FALSE;
+static void
+link_changed (NMPlatform *platform,
+ NMFakePlatformLink *device,
+ NMPCacheOpsType cache_op,
+ const NMPObject *obj_old)
+{
+ g_assert (device->obj);
- NMFakePlatformLink *master = link_get (platform, device->link.master);
+ g_assert (!nmp_cache_link_connected_needs_toggle (nm_platform_get_cache (platform),
+ device->obj, NULL, NULL));
- g_return_if_fail (master && master != device);
+ nm_platform_cache_update_emit_signal (platform,
+ cache_op,
+ obj_old,
+ device->obj);
- for (i = 0; i < priv->links->len; i++) {
- NMFakePlatformLink *slave = &g_array_index (priv->links, NMFakePlatformLink, i);
+ if (!IN6_IS_ADDR_UNSPECIFIED (&device->ip6_lladdr)) {
+ if (device->obj->link.connected)
+ ip6_address_add (platform, device->obj->link.ifindex, in6addr_any, 64, device->ip6_lladdr, NM_PLATFORM_LIFETIME_PERMANENT, NM_PLATFORM_LIFETIME_PERMANENT, 0);
+ else
+ ip6_address_delete (platform, device->obj->link.ifindex, device->ip6_lladdr, 64);
+ }
- if (slave && slave->link.master == master->link.ifindex && slave->link.connected)
- connected = TRUE;
- }
+ if (device->obj->link.master) {
+ NMFakePlatformLink *master;
- if (master->link.connected != connected) {
- master->link.connected = connected;
- link_changed (platform, master, TRUE);
- }
+ master = link_get (platform, device->obj->link.master);
+ link_set_obj (platform, master, NULL);
}
}
@@ -445,7 +495,6 @@ static gboolean
link_set_up (NMPlatform *platform, int ifindex, gboolean *out_no_firmware)
{
NMFakePlatformLink *device = link_get (platform, ifindex);
- gboolean up, connected;
if (out_no_firmware)
*out_no_firmware = FALSE;
@@ -455,29 +504,9 @@ link_set_up (NMPlatform *platform, int ifindex, gboolean *out_no_firmware)
return FALSE;
}
- up = TRUE;
- connected = TRUE;
- switch (device->link.type) {
- case NM_LINK_TYPE_DUMMY:
- case NM_LINK_TYPE_VLAN:
- break;
- case NM_LINK_TYPE_BRIDGE:
- case NM_LINK_TYPE_BOND:
- case NM_LINK_TYPE_TEAM:
- connected = FALSE;
- break;
- default:
- connected = FALSE;
- g_error ("Unexpected device type: %d", device->link.type);
- }
-
- if ( NM_FLAGS_HAS (device->link.n_ifi_flags, IFF_UP) != !!up
- || device->link.connected != connected) {
- device->link.n_ifi_flags = NM_FLAGS_ASSIGN (device->link.n_ifi_flags, IFF_UP, up);
- device->link.connected = connected;
- link_changed (platform, device, TRUE);
- }
-
+ link_set_flags (platform,
+ device,
+ NM_FLAGS_ASSIGN (device->obj->link.n_ifi_flags, IFF_UP, TRUE));
return TRUE;
}
@@ -491,13 +520,9 @@ link_set_down (NMPlatform *platform, int ifindex)
return FALSE;
}
- if (NM_FLAGS_HAS (device->link.n_ifi_flags, IFF_UP) || device->link.connected) {
- device->link.n_ifi_flags = NM_FLAGS_UNSET (device->link.n_ifi_flags, IFF_UP);
- device->link.connected = FALSE;
-
- link_changed (platform, device, TRUE);
- }
-
+ link_set_flags (platform,
+ device,
+ NM_FLAGS_UNSET (device->obj->link.n_ifi_flags, IFF_UP));
return TRUE;
}
@@ -511,10 +536,9 @@ link_set_arp (NMPlatform *platform, int ifindex)
return FALSE;
}
- device->link.n_ifi_flags = NM_FLAGS_UNSET (device->link.n_ifi_flags, IFF_NOARP);
-
- link_changed (platform, device, TRUE);
-
+ link_set_flags (platform,
+ device,
+ NM_FLAGS_UNSET (device->obj->link.n_ifi_flags, IFF_NOARP));
return TRUE;
}
@@ -528,10 +552,9 @@ link_set_noarp (NMPlatform *platform, int ifindex)
return FALSE;
}
- device->link.n_ifi_flags = NM_FLAGS_SET (device->link.n_ifi_flags, IFF_NOARP);
-
- link_changed (platform, device, TRUE);
-
+ link_set_flags (platform,
+ device,
+ NM_FLAGS_SET (device->obj->link.n_ifi_flags, IFF_NOARP));
return TRUE;
}
@@ -539,21 +562,22 @@ static NMPlatformError
link_set_address (NMPlatform *platform, int ifindex, gconstpointer addr, size_t len)
{
NMFakePlatformLink *device = link_get (platform, ifindex);
+ nm_auto_nmpobj NMPObject *obj_tmp = NULL;
- if ( !device
- || len == 0
+ if ( len == 0
|| len > NM_UTILS_HWADDR_LEN_MAX
|| !addr)
g_return_val_if_reached (NM_PLATFORM_ERROR_BUG);
- if ( device->link.addr.len != len
- || ( len > 0
- && memcmp (device->link.addr.data, addr, len) != 0)) {
- memcpy (device->link.addr.data, addr, len);
- device->link.addr.len = len;
- link_changed (platform, link_get (platform, ifindex), TRUE);
- }
+ if (!device)
+ return NM_PLATFORM_ERROR_EXISTS;
+
+ obj_tmp = nmp_object_clone (device->obj, FALSE);
+ obj_tmp->link.addr.len = len;
+ memset (obj_tmp->link.addr.data, 0, sizeof (obj_tmp->link.addr.data));
+ memcpy (obj_tmp->link.addr.data, addr, len);
+ link_set_obj (platform, device, obj_tmp);
return NM_PLATFORM_ERROR_SUCCESS;
}
@@ -561,14 +585,17 @@ static gboolean
link_set_mtu (NMPlatform *platform, int ifindex, guint32 mtu)
{
NMFakePlatformLink *device = link_get (platform, ifindex);
+ nm_auto_nmpobj NMPObject *obj_tmp = NULL;
- if (device) {
- device->link.mtu = mtu;
- link_changed (platform, device, TRUE);
- } else
+ if (!device) {
_LOGE ("failure changing link: netlink error (No such device)");
+ return FALSE;
+ }
- return !!device;
+ obj_tmp = nmp_object_clone (device->obj, FALSE);
+ obj_tmp->link.mtu = mtu;
+ link_set_obj (platform, device, obj_tmp);
+ return TRUE;
}
static gboolean
@@ -612,7 +639,7 @@ link_supports_carrier_detect (NMPlatform *platform, int ifindex)
if (!device)
return FALSE;
- switch (device->link.type) {
+ switch (device->obj->link.type) {
case NM_LINK_TYPE_DUMMY:
return FALSE;
default:
@@ -628,7 +655,7 @@ link_supports_vlans (NMPlatform *platform, int ifindex)
if (!device)
return FALSE;
- switch (device->link.type) {
+ switch (device->obj->link.type) {
case NM_LINK_TYPE_LOOPBACK:
return FALSE;
default:
@@ -644,7 +671,7 @@ link_supports_sriov (NMPlatform *platform, int ifindex)
if (!device)
return FALSE;
- switch (device->link.type) {
+ switch (device->obj->link.type) {
case NM_LINK_TYPE_LOOPBACK:
return FALSE;
default:
@@ -661,15 +688,14 @@ link_enslave (NMPlatform *platform, int master, int slave)
g_return_val_if_fail (device, FALSE);
g_return_val_if_fail (master_device, FALSE);
- if (device->link.master != master) {
- device->link.master = master;
-
- if (NM_IN_SET (master_device->link.type, NM_LINK_TYPE_BOND, NM_LINK_TYPE_TEAM)) {
- device->link.n_ifi_flags = NM_FLAGS_SET (device->link.n_ifi_flags, IFF_UP);
- device->link.connected = TRUE;
- }
+ if (device->obj->link.master != master) {
+ nm_auto_nmpobj NMPObject *obj_tmp = NULL;
- link_changed (platform, device, TRUE);
+ obj_tmp = nmp_object_clone (device->obj, FALSE);
+ obj_tmp->link.master = master;
+ if (NM_IN_SET (master_device->obj->link.type, NM_LINK_TYPE_BOND, NM_LINK_TYPE_TEAM))
+ obj_tmp->link.n_ifi_flags = NM_FLAGS_SET (device->obj->link.n_ifi_flags, IFF_UP);
+ link_set_obj (platform, device, obj_tmp);
}
return TRUE;
@@ -680,40 +706,56 @@ link_release (NMPlatform *platform, int master_idx, int slave_idx)
{
NMFakePlatformLink *master = link_get (platform, master_idx);
NMFakePlatformLink *slave = link_get (platform, slave_idx);
+ nm_auto_nmpobj NMPObject *obj_tmp = NULL;
g_return_val_if_fail (master, FALSE);
g_return_val_if_fail (slave, FALSE);
- if (slave->link.master != master->link.ifindex)
+ if (slave->obj->link.master != master->obj->link.ifindex)
return FALSE;
- slave->link.master = 0;
-
- link_changed (platform, slave, TRUE);
- link_changed (platform, master, TRUE);
-
+ obj_tmp = nmp_object_clone (slave->obj, FALSE);
+ obj_tmp->link.master = 0;
+ link_set_obj (platform, slave, obj_tmp);
return TRUE;
}
-static gboolean
-vlan_add (NMPlatform *platform, const char *name, int parent, int vlan_id, guint32 vlan_flags, const NMPlatformLink **out_link)
-{
- NMFakePlatformLink *device;
+struct vlan_add_data {
+ guint32 vlan_flags;
+ int parent;
+ int vlan_id;
+};
- if (!link_add (platform, name, NM_LINK_TYPE_VLAN, NULL, NULL, 0, out_link))
- return FALSE;
+static void
+_vlan_add_prepare (NMPlatform *platform,
+ NMFakePlatformLink *device,
+ gconstpointer user_data)
+{
+ const struct vlan_add_data *d = user_data;
+ NMPObject *obj_tmp;
+ NMPObject *lnk;
- device = link_get (platform, nm_platform_link_get_ifindex (platform, name));
+ obj_tmp = (NMPObject *) device->obj;
- g_return_val_if_fail (device, FALSE);
- g_return_val_if_fail (!device->lnk, FALSE);
+ lnk = nmp_object_new (NMP_OBJECT_TYPE_LNK_VLAN, NULL);
+ lnk->lnk_vlan.id = d->vlan_id;
+ lnk->lnk_vlan.flags = d->vlan_flags;
- device->lnk = nmp_object_new (NMP_OBJECT_TYPE_LNK_VLAN, NULL);
- device->lnk->lnk_vlan.id = vlan_id;
- device->link.parent = parent;
+ obj_tmp->link.parent = d->parent;
+ obj_tmp->_link.netlink.lnk = lnk;
+}
- if (out_link)
- *out_link = &device->link;
+static gboolean
+vlan_add (NMPlatform *platform, const char *name, int parent, int vlan_id, guint32 vlan_flags, const NMPlatformLink **out_link)
+{
+ const struct vlan_add_data d = {
+ .parent = parent,
+ .vlan_id = vlan_id,
+ .vlan_flags = vlan_flags,
+ };
+
+ link_add_one (platform, name, NM_LINK_TYPE_VLAN,
+ _vlan_add_prepare, &d, out_link);
return TRUE;
}
@@ -732,53 +774,76 @@ link_vlan_change (NMPlatform *platform,
return FALSE;
}
+static void
+_vxlan_add_prepare (NMPlatform *platform,
+ NMFakePlatformLink *device,
+ gconstpointer user_data)
+{
+ const NMPlatformLnkVxlan *props = user_data;
+ NMPObject *obj_tmp;
+ NMPObject *lnk;
+
+ obj_tmp = (NMPObject *) device->obj;
+
+ lnk = nmp_object_new (NMP_OBJECT_TYPE_LNK_VXLAN, NULL);
+ lnk->lnk_vxlan = *props;
+
+ obj_tmp->link.parent = props->parent_ifindex;
+ obj_tmp->_link.netlink.lnk = lnk;
+}
+
static gboolean
link_vxlan_add (NMPlatform *platform,
const char *name,
const NMPlatformLnkVxlan *props,
const NMPlatformLink **out_link)
{
- NMFakePlatformLink *device;
+ link_add_one (platform, name, NM_LINK_TYPE_VXLAN,
+ _vxlan_add_prepare, props, out_link);
+ return TRUE;
+}
- if (!link_add (platform, name, NM_LINK_TYPE_VXLAN, NULL, NULL, 0, out_link))
- return FALSE;
+struct infiniband_add_data {
+ int parent;
+ int p_key;
+};
- device = link_get (platform, nm_platform_link_get_ifindex (platform, name));
+static void
+_infiniband_add_prepare (NMPlatform *platform,
+ NMFakePlatformLink *device,
+ gconstpointer user_data)
+{
+ const struct infiniband_add_data *d = user_data;
+ NMPObject *obj_tmp;
+ NMPObject *lnk;
- g_return_val_if_fail (device, FALSE);
- g_return_val_if_fail (!device->lnk, FALSE);
+ obj_tmp = (NMPObject *) device->obj;
- device->lnk = nmp_object_new (NMP_OBJECT_TYPE_LNK_VXLAN, NULL);
- device->lnk->lnk_vxlan = *props;
- device->link.parent = props->parent_ifindex;
+ lnk = nmp_object_new (NMP_OBJECT_TYPE_LNK_INFINIBAND, NULL);
+ lnk->lnk_infiniband.p_key = d->p_key;
+ lnk->lnk_infiniband.mode = "datagram";
- if (out_link)
- *out_link = &device->link;
- return TRUE;
+ obj_tmp->link.parent = d->parent;
+ obj_tmp->_link.netlink.lnk = lnk;
}
static gboolean
infiniband_partition_add (NMPlatform *platform, int parent, int p_key, const NMPlatformLink **out_link)
{
- NMFakePlatformLink *device, *parent_device;
+ NMFakePlatformLink *parent_device;
char name[IFNAMSIZ];
+ const struct infiniband_add_data d = {
+ .parent = parent,
+ .p_key = p_key,
+ };
parent_device = link_get (platform, parent);
g_return_val_if_fail (parent_device != NULL, FALSE);
- nm_utils_new_infiniband_name (name, parent_device->link.name, p_key);
+ nm_utils_new_infiniband_name (name, parent_device->obj->link.name, p_key);
- if (!link_add (platform, name, NM_LINK_TYPE_INFINIBAND, NULL, NULL, 0, out_link))
- return FALSE;
-
- device = link_get (platform, nm_platform_link_get_ifindex (platform, name));
- g_return_val_if_fail (device, FALSE);
- g_return_val_if_fail (!device->lnk, FALSE);
-
- device->lnk = nmp_object_new (NMP_OBJECT_TYPE_LNK_VLAN, NULL);
- device->lnk->lnk_infiniband.p_key = p_key;
- device->lnk->lnk_infiniband.mode = "datagram";
- device->link.parent = parent;
+ link_add_one (platform, name, NM_LINK_TYPE_INFINIBAND,
+ _infiniband_add_prepare, &d, out_link);
return TRUE;
}
@@ -791,7 +856,7 @@ infiniband_partition_delete (NMPlatform *platform, int parent, int p_key)
parent_device = link_get (platform, parent);
g_return_val_if_fail (parent_device != NULL, FALSE);
- nm_utils_new_infiniband_name (name, parent_device->link.name, p_key);
+ nm_utils_new_infiniband_name (name, parent_device->obj->link.name, p_key);
return link_delete (platform, nm_platform_link_get_ifindex (platform, name));
}
@@ -802,7 +867,7 @@ wifi_get_capabilities (NMPlatform *platform, int ifindex, NMDeviceWifiCapabiliti
g_return_val_if_fail (device, FALSE);
- if (device->link.type != NM_LINK_TYPE_WIFI)
+ if (device->obj->link.type != NM_LINK_TYPE_WIFI)
return FALSE;
if (caps) {
@@ -1236,9 +1301,6 @@ nm_fake_platform_setup (void)
nm_platform_setup (platform);
- /* skip zero element */
- link_add (platform, NULL, NM_LINK_TYPE_NONE, NULL, NULL, 0, NULL);
-
/* add loopback interface */
link_add (platform, "lo", NM_LINK_TYPE_LOOPBACK, NULL, NULL, 0, NULL);
@@ -1259,7 +1321,7 @@ finalize (GObject *object)
NMFakePlatformLink *device = &g_array_index (priv->links, NMFakePlatformLink, i);
g_free (device->udi);
- g_clear_pointer (&device->lnk, nmp_object_unref);
+ g_clear_pointer (&device->obj, nmp_object_unref);
}
g_array_unref (priv->links);
@@ -1277,15 +1339,8 @@ nm_fake_platform_class_init (NMFakePlatformClass *klass)
platform_class->sysctl_set = sysctl_set;
platform_class->sysctl_get = sysctl_get;
- platform_class->link_get = _nm_platform_link_get;
- platform_class->link_get_by_ifname = _nm_platform_link_get_by_ifname;
- platform_class->link_get_by_address = _nm_platform_link_get_by_address;
- platform_class->link_get_all = link_get_all;
platform_class->link_add = link_add;
platform_class->link_delete = link_delete;
- platform_class->link_get_type_name = link_get_type_name;
-
- platform_class->link_get_lnk = link_get_lnk;
platform_class->link_get_udi = link_get_udi;
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
index 6fc24acdcb..6a4210de90 100644
--- a/src/platform/nm-linux-platform.c
+++ b/src/platform/nm-linux-platform.c
@@ -3858,108 +3858,6 @@ event_valid_msg (NMPlatform *platform, struct nl_msg *msg, gboolean handle_event
/*****************************************************************************/
-static const NMPObject *
-cache_lookup_link (NMPlatform *platform, int ifindex)
-{
- const NMPObject *obj_cache;
-
- obj_cache = nmp_cache_lookup_link (nm_platform_get_cache (platform), ifindex);
- if (!nmp_object_is_visible (obj_cache))
- return NULL;
-
- return obj_cache;
-}
-
-static GArray *
-link_get_all (NMPlatform *platform)
-{
- NMPLookup lookup;
-
- nmp_lookup_init_obj_type (&lookup, NMP_OBJECT_TYPE_LINK);
- return nmp_cache_lookup_to_array (nmp_cache_lookup (nm_platform_get_cache (platform), &lookup),
- NMP_OBJECT_TYPE_LINK,
- TRUE);
-}
-
-static const NMPlatformLink *
-_nm_platform_link_get (NMPlatform *platform, int ifindex)
-{
- const NMPObject *obj;
-
- obj = cache_lookup_link (platform, ifindex);
- return obj ? &obj->link : NULL;
-}
-
-static const NMPlatformLink *
-_nm_platform_link_get_by_ifname (NMPlatform *platform,
- const char *ifname)
-{
- const NMPObject *obj = NULL;
-
- if (ifname && *ifname) {
- obj = nmp_cache_lookup_link_full (nm_platform_get_cache (platform),
- 0, ifname, TRUE, NM_LINK_TYPE_NONE, NULL, NULL);
- }
- return obj ? &obj->link : NULL;
-}
-
-struct _nm_platform_link_get_by_address_data {
- gconstpointer address;
- guint8 length;
-};
-
-static gboolean
-_nm_platform_link_get_by_address_match_link (const NMPObject *obj, struct _nm_platform_link_get_by_address_data *d)
-{
- return obj->link.addr.len == d->length && !memcmp (obj->link.addr.data, d->address, d->length);
-}
-
-static const NMPlatformLink *
-_nm_platform_link_get_by_address (NMPlatform *platform,
- gconstpointer address,
- size_t length)
-{
- const NMPObject *obj;
- struct _nm_platform_link_get_by_address_data d = {
- .address = address,
- .length = length,
- };
-
- if (length <= 0 || length > NM_UTILS_HWADDR_LEN_MAX)
- return NULL;
- if (!address)
- return NULL;
-
- obj = nmp_cache_lookup_link_full (nm_platform_get_cache (platform),
- 0, NULL, TRUE, NM_LINK_TYPE_NONE,
- (NMPObjectMatchFn) _nm_platform_link_get_by_address_match_link, &d);
- return obj ? &obj->link : NULL;
-}
-
-/*****************************************************************************/
-
-static const NMPObject *
-link_get_lnk (NMPlatform *platform, int ifindex, NMLinkType link_type, const NMPlatformLink **out_link)
-{
- const NMPObject *obj = cache_lookup_link (platform, ifindex);
-
- if (!obj)
- return NULL;
-
- NM_SET_OUT (out_link, &obj->link);
-
- if (!obj->_link.netlink.lnk)
- return NULL;
- if ( link_type != NM_LINK_TYPE_NONE
- && ( link_type != obj->link.type
- || link_type != NMP_OBJECT_GET_CLASS (obj->_link.netlink.lnk)->lnk_link_type))
- return NULL;
-
- return obj->_link.netlink.lnk;
-}
-
-/*****************************************************************************/
-
static gboolean
do_add_link_with_lookup (NMPlatform *platform,
NMLinkType link_type,
@@ -4287,55 +4185,11 @@ link_delete (NMPlatform *platform, int ifindex)
return do_delete_object (platform, &obj_id, nlmsg);
}
-static const char *
-link_get_type_name (NMPlatform *platform, int ifindex)
-{
- const NMPObject *obj = cache_lookup_link (platform, ifindex);
-
- if (!obj)
- return NULL;
-
- if (obj->link.type != NM_LINK_TYPE_UNKNOWN) {
- /* We could detect the @link_type. In this case the function returns
- * our internel module names, which differs from rtnl_link_get_type():
- * - NM_LINK_TYPE_INFINIBAND (gives "infiniband", instead of "ipoib")
- * - NM_LINK_TYPE_TAP (gives "tap", instead of "tun").
- * Note that this functions is only used by NMDeviceGeneric to
- * set type_description. */
- return nm_link_type_to_string (obj->link.type);
- }
- /* Link type not detected. Fallback to rtnl_link_get_type()/IFLA_INFO_KIND. */
- return obj->link.kind ?: "unknown";
-}
-
-static gboolean
-link_get_unmanaged (NMPlatform *platform, int ifindex, gboolean *unmanaged)
-{
- const NMPObject *link;
- struct udev_device *udevice = NULL;
- const char *uproperty;
-
- link = nmp_cache_lookup_link (nm_platform_get_cache (platform), ifindex);
- if (!link)
- return FALSE;
-
- udevice = link->_link.udev.device;
- if (!udevice)
- return FALSE;
-
- uproperty = udev_device_get_property_value (udevice, "NM_UNMANAGED");
- if (!uproperty)
- return FALSE;
-
- *unmanaged = nm_udev_utils_property_as_boolean (uproperty);
- return TRUE;
-}
-
static gboolean
link_refresh (NMPlatform *platform, int ifindex)
{
do_request_link (platform, ifindex, NULL);
- return !!cache_lookup_link (platform, ifindex);
+ return !!nm_platform_link_get_obj (platform, ifindex, TRUE);
}
static gboolean
@@ -4422,7 +4276,7 @@ link_set_noarp (NMPlatform *platform, int ifindex)
static const char *
link_get_udi (NMPlatform *platform, int ifindex)
{
- const NMPObject *obj = cache_lookup_link (platform, ifindex);
+ const NMPObject *obj = nm_platform_link_get_obj (platform, ifindex, TRUE);
if ( !obj
|| !obj->_link.netlink.is_in_netlink
@@ -4431,20 +4285,6 @@ link_get_udi (NMPlatform *platform, int ifindex)
return udev_device_get_syspath (obj->_link.udev.device);
}
-static struct udev_device *
-link_get_udev_device (NMPlatform *platform, int ifindex)
-{
- const NMPObject *obj_cache;
-
- /* we don't use cache_lookup_link() because this would return NULL
- * if the link is not visible in libnl. For link_get_udev_device()
- * we want to return whatever we have, even if the link itself
- * appears invisible via other platform functions. */
-
- obj_cache = nmp_cache_lookup_link (nm_platform_get_cache (platform), ifindex);
- return obj_cache ? obj_cache->_link.udev.device : NULL;
-}
-
static NMPlatformError
link_set_user_ipv6ll_enabled (NMPlatform *platform, int ifindex, gboolean enabled)
{
@@ -4509,7 +4349,7 @@ link_supports_vlans (NMPlatform *platform, int ifindex)
nm_auto_pop_netns NMPNetns *netns = NULL;
const NMPObject *obj;
- obj = cache_lookup_link (platform, ifindex);
+ obj = nm_platform_link_get_obj (platform, ifindex, TRUE);
/* Only ARPHRD_ETHER links can possibly support VLANs. */
if (!obj || obj->link.arptype != ARPHRD_ETHER)
@@ -5623,7 +5463,7 @@ link_can_assume (NMPlatform *platform, int ifindex)
if (ifindex <= 0)
return FALSE;
- link = cache_lookup_link (platform, ifindex);
+ link = nm_platform_link_get_obj (platform, ifindex, TRUE);
if (!link)
return FALSE;
@@ -5647,7 +5487,7 @@ link_can_assume (NMPlatform *platform, int ifindex)
&o) {
nm_assert (NMP_OBJECT_GET_TYPE (o) == NMP_OBJECT_TYPE_IP6_ADDRESS);
if (!IN6_IS_ADDR_LINKLOCAL (&o->ip6_address.address))
- return TRUE;
+ return TRUE;
}
return FALSE;
}
@@ -6679,16 +6519,8 @@ nm_linux_platform_class_init (NMLinuxPlatformClass *klass)
platform_class->sysctl_set = sysctl_set;
platform_class->sysctl_get = sysctl_get;
- platform_class->link_get = _nm_platform_link_get;
- platform_class->link_get_by_ifname = _nm_platform_link_get_by_ifname;
- platform_class->link_get_by_address = _nm_platform_link_get_by_address;
- platform_class->link_get_all = link_get_all;
platform_class->link_add = link_add;
platform_class->link_delete = link_delete;
- platform_class->link_get_type_name = link_get_type_name;
- platform_class->link_get_unmanaged = link_get_unmanaged;
-
- platform_class->link_get_lnk = link_get_lnk;
platform_class->link_refresh = link_refresh;
@@ -6700,7 +6532,6 @@ nm_linux_platform_class_init (NMLinuxPlatformClass *klass)
platform_class->link_set_noarp = link_set_noarp;
platform_class->link_get_udi = link_get_udi;
- platform_class->link_get_udev_device = link_get_udev_device;
platform_class->link_set_user_ipv6ll_enabled = link_set_user_ipv6ll_enabled;
platform_class->link_set_token = link_set_token;
diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c
index 235cdb9c21..85a7b7c175 100644
--- a/src/platform/nm-platform.c
+++ b/src/platform/nm-platform.c
@@ -32,10 +32,12 @@
#include <linux/if_tun.h>
#include <linux/if_tunnel.h>
#include <linux/rtnetlink.h>
+#include <libudev.h>
#include "nm-utils.h"
#include "nm-core-internal.h"
#include "nm-utils/nm-dedup-multi.h"
+#include "nm-utils/nm-udev-utils.h"
#include "nm-core-utils.h"
#include "nm-platform-utils.h"
@@ -497,10 +499,14 @@ nm_platform_link_get_all (NMPlatform *self, gboolean sort_by_name)
guint i, j, nresult;
GHashTable *unseen;
NMPlatformLink *item;
+ NMPLookup lookup;
_CHECK_SELF (self, klass, NULL);
- links = klass->link_get_all (self);
+ nmp_lookup_init_obj_type (&lookup, NMP_OBJECT_TYPE_LINK);
+ links = nmp_cache_lookup_to_array (nmp_cache_lookup (nm_platform_get_cache (self), &lookup),
+ NMP_OBJECT_TYPE_LINK,
+ TRUE);
if (!links || links->len == 0)
return links;
@@ -518,7 +524,7 @@ nm_platform_link_get_all (NMPlatform *self, gboolean sort_by_name)
nm_assert_not_reached ();
}
-#ifndef G_DISABLE_ASSERT
+#if NM_MORE_ASSERTS
/* Ensure that link_get_all returns a consistent and valid result. */
for (i = 0; i < links->len; i++) {
item = &g_array_index (links, NMPlatformLink, i);
@@ -589,6 +595,25 @@ nm_platform_link_get_all (NMPlatform *self, gboolean sort_by_name)
return result;
}
+/*****************************************************************************/
+
+const NMPObject *
+nm_platform_link_get_obj (NMPlatform *self,
+ int ifindex,
+ gboolean visible_only)
+{
+ const NMPObject *obj_cache;
+
+ obj_cache = nmp_cache_lookup_link (nm_platform_get_cache (self), ifindex);
+ if ( !obj_cache
+ || ( visible_only
+ && !nmp_object_is_visible (obj_cache)))
+ return NULL;
+ return obj_cache;
+}
+
+/*****************************************************************************/
+
/**
* nm_platform_link_get:
* @self: platform instance
@@ -604,11 +629,15 @@ nm_platform_link_get_all (NMPlatform *self, gboolean sort_by_name)
const NMPlatformLink *
nm_platform_link_get (NMPlatform *self, int ifindex)
{
+ const NMPObject *obj;
+
_CHECK_SELF (self, klass, NULL);
- if (ifindex > 0)
- return klass->link_get (self, ifindex);
- return NULL;
+ if (ifindex <= 0)
+ return NULL;
+
+ obj = nm_platform_link_get_obj (self, ifindex, TRUE);
+ return NMP_OBJECT_CAST_LINK (obj);
}
/**
@@ -621,11 +650,27 @@ nm_platform_link_get (NMPlatform *self, int ifindex)
const NMPlatformLink *
nm_platform_link_get_by_ifname (NMPlatform *self, const char *ifname)
{
+ const NMPObject *obj;
+
_CHECK_SELF (self, klass, NULL);
- if (ifname && *ifname)
- return klass->link_get_by_ifname (self, ifname);
- return NULL;
+ if (!ifname || !*ifname)
+ return NULL;
+
+ obj = nmp_cache_lookup_link_full (nm_platform_get_cache (self),
+ 0, ifname, TRUE, NM_LINK_TYPE_NONE, NULL, NULL);
+ return NMP_OBJECT_CAST_LINK (obj);
+}
+
+struct _nm_platform_link_get_by_address_data {
+ gconstpointer address;
+ guint8 length;
+};
+
+static gboolean
+_nm_platform_link_get_by_address_match_link (const NMPObject *obj, struct _nm_platform_link_get_by_address_data *d)
+{
+ return obj->link.addr.len == d->length && !memcmp (obj->link.addr.data, d->address, d->length);
}
/**
@@ -642,15 +687,26 @@ nm_platform_link_get_by_address (NMPlatform *self,
gconstpointer address,
size_t length)
{
+ const NMPObject *obj;
+ struct _nm_platform_link_get_by_address_data d = {
+ .address = address,
+ .length = length,
+ };
+
_CHECK_SELF (self, klass, NULL);
- g_return_val_if_fail (length == 0 || address, NULL);
- if (length > 0) {
- if (length > NM_UTILS_HWADDR_LEN_MAX)
- g_return_val_if_reached (NULL);
- return klass->link_get_by_address (self, address, length);
- }
- return NULL;
+ if (length == 0)
+ return NULL;
+
+ if (length > NM_UTILS_HWADDR_LEN_MAX)
+ g_return_val_if_reached (NULL);
+ if (!address)
+ g_return_val_if_reached (NULL);
+
+ obj = nmp_cache_lookup_link_full (nm_platform_get_cache (self),
+ 0, NULL, TRUE, NM_LINK_TYPE_NONE,
+ (NMPObjectMatchFn) _nm_platform_link_get_by_address_match_link, &d);
+ return NMP_OBJECT_CAST_LINK (obj);
}
static NMPlatformError
@@ -880,9 +936,26 @@ nm_platform_link_get_type (NMPlatform *self, int ifindex)
const char *
nm_platform_link_get_type_name (NMPlatform *self, int ifindex)
{
+ const NMPObject *obj;
+
_CHECK_SELF (self, klass, NULL);
- return klass->link_get_type_name (self, ifindex);
+ obj = nm_platform_link_get_obj (self, ifindex, TRUE);
+
+ if (!obj)
+ return NULL;
+
+ if (obj->link.type != NM_LINK_TYPE_UNKNOWN) {
+ /* We could detect the @link_type. In this case the function returns
+ * our internel module names, which differs from rtnl_link_get_type():
+ * - NM_LINK_TYPE_INFINIBAND (gives "infiniband", instead of "ipoib")
+ * - NM_LINK_TYPE_TAP (gives "tap", instead of "tun").
+ * Note that this functions is only used by NMDeviceGeneric to
+ * set type_description. */
+ return nm_link_type_to_string (obj->link.type);
+ }
+ /* Link type not detected. Fallback to rtnl_link_get_type()/IFLA_INFO_KIND. */
+ return obj->link.kind ?: "unknown";
}
/**
@@ -897,11 +970,26 @@ nm_platform_link_get_type_name (NMPlatform *self, int ifindex)
gboolean
nm_platform_link_get_unmanaged (NMPlatform *self, int ifindex, gboolean *unmanaged)
{
+ const NMPObject *link;
+ struct udev_device *udevice = NULL;
+ const char *uproperty;
+
_CHECK_SELF (self, klass, FALSE);
- if (klass->link_get_unmanaged)
- return klass->link_get_unmanaged (self, ifindex, unmanaged);
- return FALSE;
+ link = nmp_cache_lookup_link (nm_platform_get_cache (self), ifindex);
+ if (!link)
+ return FALSE;
+
+ udevice = link->_link.udev.device;
+ if (!udevice)
+ return FALSE;
+
+ uproperty = udev_device_get_property_value (udevice, "NM_UNMANAGED");
+ if (!uproperty)
+ return FALSE;
+
+ *unmanaged = nm_udev_utils_property_as_boolean (uproperty);
+ return TRUE;
}
/**
@@ -1047,13 +1135,14 @@ nm_platform_link_get_udi (NMPlatform *self, int ifindex)
struct udev_device *
nm_platform_link_get_udev_device (NMPlatform *self, int ifindex)
{
+ const NMPObject *obj_cache;
+
_CHECK_SELF (self, klass, FALSE);
g_return_val_if_fail (ifindex >= 0, NULL);
- if (klass->link_get_udev_device)
- return klass->link_get_udev_device (self, ifindex);
- return NULL;
+ obj_cache = nm_platform_link_get_obj (self, ifindex, FALSE);
+ return obj_cache ? obj_cache->_link.udev.device : NULL;
}
/**
@@ -1553,13 +1642,28 @@ nm_platform_link_can_assume (NMPlatform *self, int ifindex)
const NMPObject *
nm_platform_link_get_lnk (NMPlatform *self, int ifindex, NMLinkType link_type, const NMPlatformLink **out_link)
{
+ const NMPObject *obj;
+
_CHECK_SELF (self, klass, FALSE);
NM_SET_OUT (out_link, NULL);
g_return_val_if_fail (ifindex > 0, NULL);
- return klass->link_get_lnk (self, ifindex, link_type, out_link);
+ obj = nm_platform_link_get_obj (self, ifindex, TRUE);
+ if (!obj)
+ return NULL;
+
+ NM_SET_OUT (out_link, &obj->link);
+
+ if (!obj->_link.netlink.lnk)
+ return NULL;
+ if ( link_type != NM_LINK_TYPE_NONE
+ && ( link_type != obj->link.type
+ || link_type != NMP_OBJECT_GET_CLASS (obj->_link.netlink.lnk)->lnk_link_type))
+ return NULL;
+
+ return obj->_link.netlink.lnk;
}
static gconstpointer
@@ -2871,8 +2975,8 @@ nm_platform_ip4_address_get (NMPlatform *self, int ifindex, in_addr_t address, g
nmp_object_stackinit_id_ip4_address (&obj_id, ifindex, address, plen, peer_address);
obj = nmp_cache_lookup_obj (nm_platform_get_cache (self), &obj_id);
- nm_assert (nmp_object_is_visible (obj));
- return &obj->ip4_address;
+ nm_assert (!obj || nmp_object_is_visible (obj));
+ return NMP_OBJECT_CAST_IP4_ADDRESS (obj);
}
const NMPlatformIP6Address *
@@ -2885,8 +2989,8 @@ nm_platform_ip6_address_get (NMPlatform *self, int ifindex, struct in6_addr addr
nmp_object_stackinit_id_ip6_address (&obj_id, ifindex, &address);
obj = nmp_cache_lookup_obj (nm_platform_get_cache (self), &obj_id);
- nm_assert (nmp_object_is_visible (obj));
- return &obj->ip6_address;
+ nm_assert (!obj || nmp_object_is_visible (obj));
+ return NMP_OBJECT_CAST_IP6_ADDRESS (obj);
}
static const NMPlatformIP4Address *
diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h
index ed95f99bed..20c8e0d9f8 100644
--- a/src/platform/nm-platform.h
+++ b/src/platform/nm-platform.h
@@ -506,13 +506,6 @@ typedef struct {
gboolean (*sysctl_set) (NMPlatform *, const char *pathid, int dirfd, const char *path, const char *value);
char * (*sysctl_get) (NMPlatform *, const char *pathid, int dirfd, const char *path);
- const NMPlatformLink *(*link_get) (NMPlatform *platform, int ifindex);
- const NMPlatformLink *(*link_get_by_ifname) (NMPlatform *platform, const char *ifname);
- const NMPlatformLink *(*link_get_by_address) (NMPlatform *platform, gconstpointer address, size_t length);
-
- const NMPObject *(*link_get_lnk) (NMPlatform *platform, int ifindex, NMLinkType link_type, const NMPlatformLink **out_link);
-
- GArray *(*link_get_all) (NMPlatform *);
gboolean (*link_add) (NMPlatform *,
const char *name,
NMLinkType type,
@@ -521,8 +514,6 @@ typedef struct {
size_t address_len,
const NMPlatformLink **out_link);
gboolean (*link_delete) (NMPlatform *, int ifindex);
- const char *(*link_get_type_name) (NMPlatform *, int ifindex);
- gboolean (*link_get_unmanaged) (NMPlatform *, int ifindex, gboolean *unmanaged);
gboolean (*link_refresh) (NMPlatform *, int ifindex);
@@ -742,6 +733,9 @@ gboolean nm_platform_sysctl_set_ip6_hop_limit_safe (NMPlatform *self, const char
const char *nm_platform_if_indextoname (NMPlatform *self, int ifindex, char *out_ifname/* of size IFNAMSIZ */);
int nm_platform_if_nametoindex (NMPlatform *self, const char *ifname);
+const NMPObject *nm_platform_link_get_obj (NMPlatform *self,
+ int ifindex,
+ gboolean visible_only);
const NMPlatformLink *nm_platform_link_get (NMPlatform *self, int ifindex);
const NMPlatformLink *nm_platform_link_get_by_ifname (NMPlatform *self, const char *ifname);
const NMPlatformLink *nm_platform_link_get_by_address (NMPlatform *self, gconstpointer address, size_t length);
diff --git a/src/platform/nmp-object.c b/src/platform/nmp-object.c
index b6f542d089..b6a51e58bc 100644
--- a/src/platform/nmp-object.c
+++ b/src/platform/nmp-object.c
@@ -1336,6 +1336,17 @@ nmp_cache_use_udev_get (const NMPCache *cache)
/*****************************************************************************/
+gboolean
+nmp_cache_link_connected_for_slave (int ifindex_master, const NMPObject *slave)
+{
+ nm_assert (NMP_OBJECT_GET_TYPE (slave) == NMP_OBJECT_TYPE_LINK);
+
+ return ifindex_master > 0
+ && slave->link.master == ifindex_master
+ && slave->link.connected
+ && nmp_object_is_visible (slave);
+}
+
/**
* nmp_cache_link_connected_needs_toggle:
* @cache: the platform cache
@@ -1378,12 +1389,9 @@ nmp_cache_link_connected_needs_toggle (const NMPCache *cache, const NMPObject *m
potential_slave = NULL;
if ( potential_slave
- && nmp_object_is_visible (potential_slave)
- && potential_slave->link.ifindex > 0
- && potential_slave->link.master == master->link.ifindex
- && potential_slave->link.connected) {
+ && nmp_cache_link_connected_for_slave (master->link.ifindex, potential_slave))
is_lower_up = TRUE;
- } else {
+ else {
NMPLookup lookup;
NMDedupMultiIter iter;
const NMPlatformLink *link = NULL;
@@ -1397,10 +1405,7 @@ nmp_cache_link_connected_needs_toggle (const NMPCache *cache, const NMPObject *m
if ( (!potential_slave || potential_slave->link.ifindex != link->ifindex)
&& ignore_slave != obj
- && link->ifindex > 0
- && link->master == master->link.ifindex
- && nmp_object_is_visible (obj)
- && link->connected) {
+ && nmp_cache_link_connected_for_slave (master->link.ifindex, obj)) {
is_lower_up = TRUE;
break;
}
diff --git a/src/platform/nmp-object.h b/src/platform/nmp-object.h
index c3095178ae..9ea5a78ae5 100644
--- a/src/platform/nmp-object.h
+++ b/src/platform/nmp-object.h
@@ -337,13 +337,22 @@ NMP_OBJECT_GET_TYPE (const NMPObject *obj)
return obj ? obj->_class->obj_type : NMP_OBJECT_TYPE_UNKNOWN;
}
+#define NMP_OBJECT_CAST_LINK(obj) \
+ ({ \
+ typeof (*(obj)) *_obj = (obj); \
+ _nm_unused const NMPObject *_obj_type_check = _obj; \
+ \
+ nm_assert (!_obj || NMP_OBJECT_GET_TYPE (_obj) == NMP_OBJECT_TYPE_LINK); \
+ _obj ? &_obj->link : NULL; \
+ })
+
#define NMP_OBJECT_CAST_IP4_ADDRESS(obj) \
({ \
typeof (*(obj)) *_obj = (obj); \
_nm_unused const NMPObject *_obj_type_check = _obj; \
\
- nm_assert (NMP_OBJECT_GET_TYPE (_obj) == NMP_OBJECT_TYPE_IP4_ADDRESS); \
- &_obj->ip4_address; \
+ nm_assert (!_obj || NMP_OBJECT_GET_TYPE (_obj) == NMP_OBJECT_TYPE_IP4_ADDRESS); \
+ _obj ? &_obj->ip4_address : NULL; \
})
#define NMP_OBJECT_CAST_IP6_ADDRESS(obj) \
@@ -351,8 +360,8 @@ NMP_OBJECT_GET_TYPE (const NMPObject *obj)
typeof (*(obj)) *_obj = (obj); \
_nm_unused const NMPObject *_obj_type_check = _obj; \
\
- nm_assert (NMP_OBJECT_GET_TYPE (_obj) == NMP_OBJECT_TYPE_IP6_ADDRESS); \
- &_obj->ip6_address; \
+ nm_assert (!_obj || NMP_OBJECT_GET_TYPE (_obj) == NMP_OBJECT_TYPE_IP6_ADDRESS); \
+ _obj ? &_obj->ip6_address : NULL; \
})
#define NMP_OBJECT_CAST_IPX_ROUTE(obj) \
@@ -541,6 +550,7 @@ const NMPObject *nmp_cache_lookup_link_full (const NMPCache *cache,
NMPObjectMatchFn match_fn,
gpointer user_data);
+gboolean nmp_cache_link_connected_for_slave (int ifindex_master, const NMPObject *slave);
gboolean nmp_cache_link_connected_needs_toggle (const NMPCache *cache, const NMPObject *master, const NMPObject *potential_slave, const NMPObject *ignore_slave);
const NMPObject *nmp_cache_link_connected_needs_toggle_by_ifindex (const NMPCache *cache, int master_ifindex, const NMPObject *potential_slave, const NMPObject *ignore_slave);
diff --git a/src/platform/tests/test-link.c b/src/platform/tests/test-link.c
index df204b4683..0e5fcbe453 100644
--- a/src/platform/tests/test-link.c
+++ b/src/platform/tests/test-link.c
@@ -264,7 +264,8 @@ test_slave (int master, int type, SignalData *master_changed)
}
g_assert (!nm_platform_link_is_up (NM_PLATFORM_GET, ifindex));
g_assert (!nm_platform_link_is_connected (NM_PLATFORM_GET, ifindex));
- if (nm_platform_link_is_connected (NM_PLATFORM_GET, master)) {
+ if ( nmtstp_is_root_test ()
+ && nm_platform_link_is_connected (NM_PLATFORM_GET, master)) {
if (nm_platform_link_get_type (NM_PLATFORM_GET, master) == NM_LINK_TYPE_TEAM) {
/* Older team versions (e.g. Fedora 17) have a bug that team master stays
* IFF_LOWER_UP even if its slave is down. Double check it with iproute2 and if
@@ -285,7 +286,7 @@ test_slave (int master, int type, SignalData *master_changed)
g_assert (nm_platform_link_is_connected (NM_PLATFORM_GET, master));
accept_signals (link_changed, 1, 3);
/* NM running, can cause additional change of addrgenmode */
- accept_signals (master_changed, 1, 2);
+ accept_signals (master_changed, 0, 2);
/* Enslave again
*
@@ -327,7 +328,7 @@ test_slave (int master, int type, SignalData *master_changed)
ensure_no_signal (link_changed);
accept_signal (link_removed);
}
- accept_signals (master_changed, 1, 2);
+ accept_signals (master_changed, 0, 2);
ensure_no_signal (master_changed);