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().
This commit is contained in:
Thomas Haller
2017-07-04 12:49:47 +02:00
parent 71cf60e852
commit ac60b0ce60
7 changed files with 552 additions and 552 deletions

View File

@@ -40,10 +40,8 @@
/*****************************************************************************/ /*****************************************************************************/
typedef struct { typedef struct {
NMPlatformLink link; const NMPObject *obj;
char *udi; char *udi;
NMPObject *lnk;
struct in6_addr ip6_lladdr; struct in6_addr ip6_lladdr;
} NMFakePlatformLink; } 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, static gboolean ipx_address_delete (NMPlatform *platform,
int addr_family, 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)); 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 * static NMFakePlatformLink *
link_get (NMPlatform *platform, int ifindex) link_get (NMPlatform *platform, int ifindex)
{ {
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE ((NMFakePlatform *) platform); NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE ((NMFakePlatform *) platform);
NMFakePlatformLink *device; NMFakePlatformLink *device;
int idx;
if (ifindex >= priv->links->len) if (ifindex <= 0)
g_return_val_if_reached (NULL);
idx = ifindex - 1;
if (idx >= priv->links->len)
goto not_found; 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; 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; return device;
not_found: not_found:
_LOGD ("link not found: %d", ifindex); _LOGD ("link not found: %d", ifindex);
return NULL; return NULL;
} }
static GArray * static void
link_get_all (NMPlatform *platform) link_add_prepare (NMPlatform *platform,
NMFakePlatformLink *device,
NMPObject *obj_tmp)
{
gboolean connected;
/* 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;
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);
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 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); NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE ((NMFakePlatform *) platform);
GArray *links = g_array_sized_new (TRUE, TRUE, sizeof (NMPlatformLink), priv->links->len); NMFakePlatformLink *device;
int i; int ifindex;
NMPObject *o;
NMPlatformLink *link;
gs_free char *ip6_lladdr = NULL;
for (i = 0; i < priv->links->len; i++) g_assert (!name || strlen (name) < IFNAMSIZ);
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; 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;
memset (device, 0, sizeof (*device));
o = nmp_object_new_link (ifindex);
link = NMP_OBJECT_CAST_LINK (o);
ip6_lladdr = ifindex > 0 ? g_strdup_printf ("fe80::fa1e:%0x:%0x", ifindex / 256, ifindex % 256) : NULL;
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;
} }
static const NMPlatformLink * o->_link.netlink.is_in_netlink = TRUE;
_nm_platform_link_get (NMPlatform *platform, int ifindex)
{
NMFakePlatformLink *device = link_get (platform, ifindex);
return device ? &device->link : NULL; 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);
static const NMPlatformLink * device->obj = o;
_nm_platform_link_get_by_ifname (NMPlatform *platform, const char *ifname) device->udi = g_strdup_printf ("fake:%d", ifindex);
{ device->ip6_lladdr = *nmtst_inet6_from_string (ip6_lladdr);
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE ((NMFakePlatform *) platform);
guint i;
for (i = 0; i < priv->links->len; i++) { return device;
NMFakePlatformLink *device = &g_array_index (priv->links, NMFakePlatformLink, i);
if (!strcmp (device->link.name, ifname))
return &device->link;
}
return NULL;
}
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;
if ( length == 0
|| length > NM_UTILS_HWADDR_LEN_MAX
|| !address)
g_return_val_if_reached (NULL);
for (i = 0; i < priv->links->len; i++) {
NMFakePlatformLink *device = &g_array_index (priv->links, NMFakePlatformLink, i);
if ( device->link.addr.len == length
&& memcmp (device->link.addr.data, address, length) == 0) {
return &device->link;
}
}
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;
if (link_type == NM_LINK_TYPE_NONE)
return device->lnk;
if ( link_type != device->link.type
|| link_type != NMP_OBJECT_GET_CLASS (device->lnk)->lnk_link_type)
return NULL;
return device->lnk;
} }
static gboolean static gboolean
@@ -331,113 +293,201 @@ link_add (NMPlatform *platform,
size_t address_len, size_t address_len,
const NMPlatformLink **out_link) const NMPlatformLink **out_link)
{ {
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE ((NMFakePlatform *) platform); NMFakePlatformLink *device;
NMFakePlatformLink device; NMFakePlatformLink *device_veth = NULL;
NMFakePlatformLink device_veth = { }; nm_auto_nmpobj const NMPObject *obj_old = NULL;
NMFakePlatformLink *new_device; 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;
link_init (&device, priv->links->len, type, name); device = link_add_pre (platform, name, type, address, address_len);
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;
}
g_array_append_val (priv->links, device);
new_device = &g_array_index (priv->links, NMFakePlatformLink, priv->links->len - 1);
if (veth_peer) { if (veth_peer) {
link_init (&device_veth, priv->links->len, type, veth_peer); g_assert (type == NM_LINK_TYPE_VETH);
g_array_append_val (priv->links, device_veth); device_veth = link_add_pre (platform, veth_peer, type, NULL, 0);
new_device = &g_array_index (priv->links, NMFakePlatformLink, priv->links->len - 2);
} else } else
g_assert (type != NM_LINK_TYPE_VETH); 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) if (out_link)
*out_link = &new_device->link; *out_link = NMP_OBJECT_CAST_LINK (device->obj);
if (device.link.ifindex) { link_changed (platform, device, cache_op, NULL);
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); if (veth_peer)
link_changed (platform, device_veth, cache_op_veth, NULL);
link_changed (platform, new_device, FALSE);
}
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);
link_changed (platform, &g_array_index (priv->links, NMFakePlatformLink, priv->links->len - 1), FALSE);
}
return TRUE; return TRUE;
} }
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;
device = link_add_pre (platform, name, NM_LINK_TYPE_VLAN, NULL, 0);
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 static gboolean
link_delete (NMPlatform *platform, int ifindex) link_delete (NMPlatform *platform, int ifindex)
{ {
NMFakePlatformLink *device = link_get (platform, 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; return FALSE;
memcpy (&deleted_device, &device->link, sizeof (deleted_device)); obj_old = g_steal_pointer (&device->obj);
memset (&device->link, 0, sizeof (device->link));
g_clear_pointer (&device->lnk, nmp_object_unref);
g_clear_pointer (&device->udi, g_free); 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 */ /* 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_INET, ifindex, NULL, NULL, NULL);
ipx_address_delete (platform, AF_INET6, 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_INET, ifindex, NULL, NULL, NULL);
ipx_route_delete (platform, AF_INET6, 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; return TRUE;
} }
static const char * static void
link_get_type_name (NMPlatform *platform, int ifindex) 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 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); nm_auto_nmpobj NMPObject *obj_tmp = NULL;
int i;
if (raise_signal) g_assert (device);
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 (NMP_OBJECT_GET_TYPE (device->obj) == NMP_OBJECT_TYPE_LINK);
if (device->link.ifindex && !IN6_IS_ADDR_UNSPECIFIED (&device->ip6_lladdr)) { obj_tmp = nmp_object_clone (device->obj, FALSE);
if (device->link.connected) obj_tmp->link.n_ifi_flags = n_ifi_flags;
ip6_address_add (platform, device->link.ifindex, in6addr_any, 64, device->ip6_lladdr, NM_PLATFORM_LIFETIME_PERMANENT, NM_PLATFORM_LIFETIME_PERMANENT, 0); link_set_obj (platform, device, obj_tmp);
}
static void
link_changed (NMPlatform *platform,
NMFakePlatformLink *device,
NMPCacheOpsType cache_op,
const NMPObject *obj_old)
{
g_assert (device->obj);
g_assert (!nmp_cache_link_connected_needs_toggle (nm_platform_get_cache (platform),
device->obj, NULL, NULL));
nm_platform_cache_update_emit_signal (platform,
cache_op,
obj_old,
device->obj);
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 else
ip6_address_delete (platform, device->link.ifindex, device->ip6_lladdr, 64); ip6_address_delete (platform, device->obj->link.ifindex, device->ip6_lladdr, 64);
} }
if (device->link.master) { if (device->obj->link.master) {
gboolean connected = FALSE; NMFakePlatformLink *master;
NMFakePlatformLink *master = link_get (platform, device->link.master); master = link_get (platform, device->obj->link.master);
link_set_obj (platform, master, NULL);
g_return_if_fail (master && master != device);
for (i = 0; i < priv->links->len; i++) {
NMFakePlatformLink *slave = &g_array_index (priv->links, NMFakePlatformLink, i);
if (slave && slave->link.master == master->link.ifindex && slave->link.connected)
connected = TRUE;
}
if (master->link.connected != connected) {
master->link.connected = connected;
link_changed (platform, master, TRUE);
}
} }
} }
@@ -445,7 +495,6 @@ static gboolean
link_set_up (NMPlatform *platform, int ifindex, gboolean *out_no_firmware) link_set_up (NMPlatform *platform, int ifindex, gboolean *out_no_firmware)
{ {
NMFakePlatformLink *device = link_get (platform, ifindex); NMFakePlatformLink *device = link_get (platform, ifindex);
gboolean up, connected;
if (out_no_firmware) if (out_no_firmware)
*out_no_firmware = FALSE; *out_no_firmware = FALSE;
@@ -455,29 +504,9 @@ link_set_up (NMPlatform *platform, int ifindex, gboolean *out_no_firmware)
return FALSE; return FALSE;
} }
up = TRUE; link_set_flags (platform,
connected = TRUE; device,
switch (device->link.type) { NM_FLAGS_ASSIGN (device->obj->link.n_ifi_flags, IFF_UP, TRUE));
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);
}
return TRUE; return TRUE;
} }
@@ -491,13 +520,9 @@ link_set_down (NMPlatform *platform, int ifindex)
return FALSE; return FALSE;
} }
if (NM_FLAGS_HAS (device->link.n_ifi_flags, IFF_UP) || device->link.connected) { link_set_flags (platform,
device->link.n_ifi_flags = NM_FLAGS_UNSET (device->link.n_ifi_flags, IFF_UP); device,
device->link.connected = FALSE; NM_FLAGS_UNSET (device->obj->link.n_ifi_flags, IFF_UP));
link_changed (platform, device, TRUE);
}
return TRUE; return TRUE;
} }
@@ -511,10 +536,9 @@ link_set_arp (NMPlatform *platform, int ifindex)
return FALSE; return FALSE;
} }
device->link.n_ifi_flags = NM_FLAGS_UNSET (device->link.n_ifi_flags, IFF_NOARP); link_set_flags (platform,
device,
link_changed (platform, device, TRUE); NM_FLAGS_UNSET (device->obj->link.n_ifi_flags, IFF_NOARP));
return TRUE; return TRUE;
} }
@@ -528,10 +552,9 @@ link_set_noarp (NMPlatform *platform, int ifindex)
return FALSE; return FALSE;
} }
device->link.n_ifi_flags = NM_FLAGS_SET (device->link.n_ifi_flags, IFF_NOARP); link_set_flags (platform,
device,
link_changed (platform, device, TRUE); NM_FLAGS_SET (device->obj->link.n_ifi_flags, IFF_NOARP));
return TRUE; return TRUE;
} }
@@ -539,21 +562,22 @@ static NMPlatformError
link_set_address (NMPlatform *platform, int ifindex, gconstpointer addr, size_t len) link_set_address (NMPlatform *platform, int ifindex, gconstpointer addr, size_t len)
{ {
NMFakePlatformLink *device = link_get (platform, ifindex); NMFakePlatformLink *device = link_get (platform, ifindex);
nm_auto_nmpobj NMPObject *obj_tmp = NULL;
if ( !device if ( len == 0
|| len == 0
|| len > NM_UTILS_HWADDR_LEN_MAX || len > NM_UTILS_HWADDR_LEN_MAX
|| !addr) || !addr)
g_return_val_if_reached (NM_PLATFORM_ERROR_BUG); g_return_val_if_reached (NM_PLATFORM_ERROR_BUG);
if ( device->link.addr.len != len if (!device)
|| ( len > 0 return NM_PLATFORM_ERROR_EXISTS;
&& 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);
}
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; return NM_PLATFORM_ERROR_SUCCESS;
} }
@@ -561,14 +585,17 @@ static gboolean
link_set_mtu (NMPlatform *platform, int ifindex, guint32 mtu) link_set_mtu (NMPlatform *platform, int ifindex, guint32 mtu)
{ {
NMFakePlatformLink *device = link_get (platform, ifindex); NMFakePlatformLink *device = link_get (platform, ifindex);
nm_auto_nmpobj NMPObject *obj_tmp = NULL;
if (device) { if (!device) {
device->link.mtu = mtu;
link_changed (platform, device, TRUE);
} else
_LOGE ("failure changing link: netlink error (No such 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 static gboolean
@@ -612,7 +639,7 @@ link_supports_carrier_detect (NMPlatform *platform, int ifindex)
if (!device) if (!device)
return FALSE; return FALSE;
switch (device->link.type) { switch (device->obj->link.type) {
case NM_LINK_TYPE_DUMMY: case NM_LINK_TYPE_DUMMY:
return FALSE; return FALSE;
default: default:
@@ -628,7 +655,7 @@ link_supports_vlans (NMPlatform *platform, int ifindex)
if (!device) if (!device)
return FALSE; return FALSE;
switch (device->link.type) { switch (device->obj->link.type) {
case NM_LINK_TYPE_LOOPBACK: case NM_LINK_TYPE_LOOPBACK:
return FALSE; return FALSE;
default: default:
@@ -644,7 +671,7 @@ link_supports_sriov (NMPlatform *platform, int ifindex)
if (!device) if (!device)
return FALSE; return FALSE;
switch (device->link.type) { switch (device->obj->link.type) {
case NM_LINK_TYPE_LOOPBACK: case NM_LINK_TYPE_LOOPBACK:
return FALSE; return FALSE;
default: 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 (device, FALSE);
g_return_val_if_fail (master_device, FALSE); g_return_val_if_fail (master_device, FALSE);
if (device->link.master != master) { if (device->obj->link.master != master) {
device->link.master = master; nm_auto_nmpobj NMPObject *obj_tmp = NULL;
if (NM_IN_SET (master_device->link.type, NM_LINK_TYPE_BOND, NM_LINK_TYPE_TEAM)) { obj_tmp = nmp_object_clone (device->obj, FALSE);
device->link.n_ifi_flags = NM_FLAGS_SET (device->link.n_ifi_flags, IFF_UP); obj_tmp->link.master = master;
device->link.connected = TRUE; 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);
link_changed (platform, device, TRUE);
} }
return TRUE; return TRUE;
@@ -680,40 +706,56 @@ link_release (NMPlatform *platform, int master_idx, int slave_idx)
{ {
NMFakePlatformLink *master = link_get (platform, master_idx); NMFakePlatformLink *master = link_get (platform, master_idx);
NMFakePlatformLink *slave = link_get (platform, slave_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 (master, FALSE);
g_return_val_if_fail (slave, 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; return FALSE;
slave->link.master = 0; obj_tmp = nmp_object_clone (slave->obj, FALSE);
obj_tmp->link.master = 0;
link_changed (platform, slave, TRUE); link_set_obj (platform, slave, obj_tmp);
link_changed (platform, master, TRUE);
return TRUE; return TRUE;
} }
struct vlan_add_data {
guint32 vlan_flags;
int parent;
int vlan_id;
};
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;
obj_tmp = (NMPObject *) device->obj;
lnk = nmp_object_new (NMP_OBJECT_TYPE_LNK_VLAN, NULL);
lnk->lnk_vlan.id = d->vlan_id;
lnk->lnk_vlan.flags = d->vlan_flags;
obj_tmp->link.parent = d->parent;
obj_tmp->_link.netlink.lnk = lnk;
}
static gboolean static gboolean
vlan_add (NMPlatform *platform, const char *name, int parent, int vlan_id, guint32 vlan_flags, const NMPlatformLink **out_link) vlan_add (NMPlatform *platform, const char *name, int parent, int vlan_id, guint32 vlan_flags, const NMPlatformLink **out_link)
{ {
NMFakePlatformLink *device; const struct vlan_add_data d = {
.parent = parent,
.vlan_id = vlan_id,
.vlan_flags = vlan_flags,
};
if (!link_add (platform, name, NM_LINK_TYPE_VLAN, NULL, NULL, 0, out_link)) link_add_one (platform, name, NM_LINK_TYPE_VLAN,
return FALSE; _vlan_add_prepare, &d, out_link);
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_vlan.id = vlan_id;
device->link.parent = parent;
if (out_link)
*out_link = &device->link;
return TRUE; return TRUE;
} }
@@ -732,53 +774,76 @@ link_vlan_change (NMPlatform *platform,
return FALSE; 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 static gboolean
link_vxlan_add (NMPlatform *platform, link_vxlan_add (NMPlatform *platform,
const char *name, const char *name,
const NMPlatformLnkVxlan *props, const NMPlatformLnkVxlan *props,
const NMPlatformLink **out_link) const NMPlatformLink **out_link)
{ {
NMFakePlatformLink *device; link_add_one (platform, name, NM_LINK_TYPE_VXLAN,
_vxlan_add_prepare, props, out_link);
if (!link_add (platform, name, NM_LINK_TYPE_VXLAN, 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_VXLAN, NULL);
device->lnk->lnk_vxlan = *props;
device->link.parent = props->parent_ifindex;
if (out_link)
*out_link = &device->link;
return TRUE; return TRUE;
} }
struct infiniband_add_data {
int parent;
int p_key;
};
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;
obj_tmp = (NMPObject *) device->obj;
lnk = nmp_object_new (NMP_OBJECT_TYPE_LNK_INFINIBAND, NULL);
lnk->lnk_infiniband.p_key = d->p_key;
lnk->lnk_infiniband.mode = "datagram";
obj_tmp->link.parent = d->parent;
obj_tmp->_link.netlink.lnk = lnk;
}
static gboolean static gboolean
infiniband_partition_add (NMPlatform *platform, int parent, int p_key, const NMPlatformLink **out_link) infiniband_partition_add (NMPlatform *platform, int parent, int p_key, const NMPlatformLink **out_link)
{ {
NMFakePlatformLink *device, *parent_device; NMFakePlatformLink *parent_device;
char name[IFNAMSIZ]; char name[IFNAMSIZ];
const struct infiniband_add_data d = {
.parent = parent,
.p_key = p_key,
};
parent_device = link_get (platform, parent); parent_device = link_get (platform, parent);
g_return_val_if_fail (parent_device != NULL, FALSE); 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)) link_add_one (platform, name, NM_LINK_TYPE_INFINIBAND,
return FALSE; _infiniband_add_prepare, &d, out_link);
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;
return TRUE; return TRUE;
} }
@@ -791,7 +856,7 @@ infiniband_partition_delete (NMPlatform *platform, int parent, int p_key)
parent_device = link_get (platform, parent); parent_device = link_get (platform, parent);
g_return_val_if_fail (parent_device != NULL, FALSE); 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)); 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); 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; return FALSE;
if (caps) { if (caps) {
@@ -1236,9 +1301,6 @@ nm_fake_platform_setup (void)
nm_platform_setup (platform); nm_platform_setup (platform);
/* skip zero element */
link_add (platform, NULL, NM_LINK_TYPE_NONE, NULL, NULL, 0, NULL);
/* add loopback interface */ /* add loopback interface */
link_add (platform, "lo", NM_LINK_TYPE_LOOPBACK, NULL, NULL, 0, NULL); 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); NMFakePlatformLink *device = &g_array_index (priv->links, NMFakePlatformLink, i);
g_free (device->udi); 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); 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_set = sysctl_set;
platform_class->sysctl_get = sysctl_get; 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_add = link_add;
platform_class->link_delete = link_delete; 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; platform_class->link_get_udi = link_get_udi;

View File

@@ -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 static gboolean
do_add_link_with_lookup (NMPlatform *platform, do_add_link_with_lookup (NMPlatform *platform,
NMLinkType link_type, NMLinkType link_type,
@@ -4287,55 +4185,11 @@ link_delete (NMPlatform *platform, int ifindex)
return do_delete_object (platform, &obj_id, nlmsg); 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 static gboolean
link_refresh (NMPlatform *platform, int ifindex) link_refresh (NMPlatform *platform, int ifindex)
{ {
do_request_link (platform, ifindex, NULL); do_request_link (platform, ifindex, NULL);
return !!cache_lookup_link (platform, ifindex); return !!nm_platform_link_get_obj (platform, ifindex, TRUE);
} }
static gboolean static gboolean
@@ -4422,7 +4276,7 @@ link_set_noarp (NMPlatform *platform, int ifindex)
static const char * static const char *
link_get_udi (NMPlatform *platform, int ifindex) 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 if ( !obj
|| !obj->_link.netlink.is_in_netlink || !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); 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 static NMPlatformError
link_set_user_ipv6ll_enabled (NMPlatform *platform, int ifindex, gboolean enabled) 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; nm_auto_pop_netns NMPNetns *netns = NULL;
const NMPObject *obj; 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. */ /* Only ARPHRD_ETHER links can possibly support VLANs. */
if (!obj || obj->link.arptype != ARPHRD_ETHER) if (!obj || obj->link.arptype != ARPHRD_ETHER)
@@ -5623,7 +5463,7 @@ link_can_assume (NMPlatform *platform, int ifindex)
if (ifindex <= 0) if (ifindex <= 0)
return FALSE; return FALSE;
link = cache_lookup_link (platform, ifindex); link = nm_platform_link_get_obj (platform, ifindex, TRUE);
if (!link) if (!link)
return FALSE; return FALSE;
@@ -6679,16 +6519,8 @@ nm_linux_platform_class_init (NMLinuxPlatformClass *klass)
platform_class->sysctl_set = sysctl_set; platform_class->sysctl_set = sysctl_set;
platform_class->sysctl_get = sysctl_get; 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_add = link_add;
platform_class->link_delete = link_delete; 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; 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_set_noarp = link_set_noarp;
platform_class->link_get_udi = link_get_udi; 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_user_ipv6ll_enabled = link_set_user_ipv6ll_enabled;
platform_class->link_set_token = link_set_token; platform_class->link_set_token = link_set_token;

View File

@@ -32,10 +32,12 @@
#include <linux/if_tun.h> #include <linux/if_tun.h>
#include <linux/if_tunnel.h> #include <linux/if_tunnel.h>
#include <linux/rtnetlink.h> #include <linux/rtnetlink.h>
#include <libudev.h>
#include "nm-utils.h" #include "nm-utils.h"
#include "nm-core-internal.h" #include "nm-core-internal.h"
#include "nm-utils/nm-dedup-multi.h" #include "nm-utils/nm-dedup-multi.h"
#include "nm-utils/nm-udev-utils.h"
#include "nm-core-utils.h" #include "nm-core-utils.h"
#include "nm-platform-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; guint i, j, nresult;
GHashTable *unseen; GHashTable *unseen;
NMPlatformLink *item; NMPlatformLink *item;
NMPLookup lookup;
_CHECK_SELF (self, klass, NULL); _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) if (!links || links->len == 0)
return links; return links;
@@ -518,7 +524,7 @@ nm_platform_link_get_all (NMPlatform *self, gboolean sort_by_name)
nm_assert_not_reached (); nm_assert_not_reached ();
} }
#ifndef G_DISABLE_ASSERT #if NM_MORE_ASSERTS
/* Ensure that link_get_all returns a consistent and valid result. */ /* Ensure that link_get_all returns a consistent and valid result. */
for (i = 0; i < links->len; i++) { for (i = 0; i < links->len; i++) {
item = &g_array_index (links, NMPlatformLink, 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; 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: * nm_platform_link_get:
* @self: platform instance * @self: platform instance
@@ -604,11 +629,15 @@ nm_platform_link_get_all (NMPlatform *self, gboolean sort_by_name)
const NMPlatformLink * const NMPlatformLink *
nm_platform_link_get (NMPlatform *self, int ifindex) nm_platform_link_get (NMPlatform *self, int ifindex)
{ {
const NMPObject *obj;
_CHECK_SELF (self, klass, NULL); _CHECK_SELF (self, klass, NULL);
if (ifindex > 0) if (ifindex <= 0)
return klass->link_get (self, ifindex);
return NULL; 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 * const NMPlatformLink *
nm_platform_link_get_by_ifname (NMPlatform *self, const char *ifname) nm_platform_link_get_by_ifname (NMPlatform *self, const char *ifname)
{ {
const NMPObject *obj;
_CHECK_SELF (self, klass, NULL); _CHECK_SELF (self, klass, NULL);
if (ifname && *ifname) if (!ifname || !*ifname)
return klass->link_get_by_ifname (self, ifname);
return NULL; 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, gconstpointer address,
size_t length) size_t length)
{ {
const NMPObject *obj;
struct _nm_platform_link_get_by_address_data d = {
.address = address,
.length = length,
};
_CHECK_SELF (self, klass, NULL); _CHECK_SELF (self, klass, NULL);
g_return_val_if_fail (length == 0 || address, NULL); if (length == 0)
if (length > 0) { return NULL;
if (length > NM_UTILS_HWADDR_LEN_MAX) if (length > NM_UTILS_HWADDR_LEN_MAX)
g_return_val_if_reached (NULL); g_return_val_if_reached (NULL);
return klass->link_get_by_address (self, address, length); if (!address)
} g_return_val_if_reached (NULL);
return 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 static NMPlatformError
@@ -880,9 +936,26 @@ nm_platform_link_get_type (NMPlatform *self, int ifindex)
const char * const char *
nm_platform_link_get_type_name (NMPlatform *self, int ifindex) nm_platform_link_get_type_name (NMPlatform *self, int ifindex)
{ {
const NMPObject *obj;
_CHECK_SELF (self, klass, NULL); _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 gboolean
nm_platform_link_get_unmanaged (NMPlatform *self, int ifindex, gboolean *unmanaged) 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); _CHECK_SELF (self, klass, FALSE);
if (klass->link_get_unmanaged) link = nmp_cache_lookup_link (nm_platform_get_cache (self), ifindex);
return klass->link_get_unmanaged (self, ifindex, unmanaged); if (!link)
return FALSE; 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 * struct udev_device *
nm_platform_link_get_udev_device (NMPlatform *self, int ifindex) nm_platform_link_get_udev_device (NMPlatform *self, int ifindex)
{ {
const NMPObject *obj_cache;
_CHECK_SELF (self, klass, FALSE); _CHECK_SELF (self, klass, FALSE);
g_return_val_if_fail (ifindex >= 0, NULL); g_return_val_if_fail (ifindex >= 0, NULL);
if (klass->link_get_udev_device) obj_cache = nm_platform_link_get_obj (self, ifindex, FALSE);
return klass->link_get_udev_device (self, ifindex); return obj_cache ? obj_cache->_link.udev.device : NULL;
return NULL;
} }
/** /**
@@ -1553,13 +1642,28 @@ nm_platform_link_can_assume (NMPlatform *self, int ifindex)
const NMPObject * const NMPObject *
nm_platform_link_get_lnk (NMPlatform *self, int ifindex, NMLinkType link_type, const NMPlatformLink **out_link) nm_platform_link_get_lnk (NMPlatform *self, int ifindex, NMLinkType link_type, const NMPlatformLink **out_link)
{ {
const NMPObject *obj;
_CHECK_SELF (self, klass, FALSE); _CHECK_SELF (self, klass, FALSE);
NM_SET_OUT (out_link, NULL); NM_SET_OUT (out_link, NULL);
g_return_val_if_fail (ifindex > 0, 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 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); 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); obj = nmp_cache_lookup_obj (nm_platform_get_cache (self), &obj_id);
nm_assert (nmp_object_is_visible (obj)); nm_assert (!obj || nmp_object_is_visible (obj));
return &obj->ip4_address; return NMP_OBJECT_CAST_IP4_ADDRESS (obj);
} }
const NMPlatformIP6Address * 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); nmp_object_stackinit_id_ip6_address (&obj_id, ifindex, &address);
obj = nmp_cache_lookup_obj (nm_platform_get_cache (self), &obj_id); obj = nmp_cache_lookup_obj (nm_platform_get_cache (self), &obj_id);
nm_assert (nmp_object_is_visible (obj)); nm_assert (!obj || nmp_object_is_visible (obj));
return &obj->ip6_address; return NMP_OBJECT_CAST_IP6_ADDRESS (obj);
} }
static const NMPlatformIP4Address * static const NMPlatformIP4Address *

View File

@@ -506,13 +506,6 @@ typedef struct {
gboolean (*sysctl_set) (NMPlatform *, const char *pathid, int dirfd, const char *path, const char *value); 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); 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 *, gboolean (*link_add) (NMPlatform *,
const char *name, const char *name,
NMLinkType type, NMLinkType type,
@@ -521,8 +514,6 @@ typedef struct {
size_t address_len, size_t address_len,
const NMPlatformLink **out_link); const NMPlatformLink **out_link);
gboolean (*link_delete) (NMPlatform *, int ifindex); 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); 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 */); 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); 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 (NMPlatform *self, int ifindex);
const NMPlatformLink *nm_platform_link_get_by_ifname (NMPlatform *self, const char *ifname); 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); const NMPlatformLink *nm_platform_link_get_by_address (NMPlatform *self, gconstpointer address, size_t length);

View File

@@ -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: * nmp_cache_link_connected_needs_toggle:
* @cache: the platform cache * @cache: the platform cache
@@ -1378,12 +1389,9 @@ nmp_cache_link_connected_needs_toggle (const NMPCache *cache, const NMPObject *m
potential_slave = NULL; potential_slave = NULL;
if ( potential_slave if ( potential_slave
&& nmp_object_is_visible (potential_slave) && nmp_cache_link_connected_for_slave (master->link.ifindex, potential_slave))
&& potential_slave->link.ifindex > 0
&& potential_slave->link.master == master->link.ifindex
&& potential_slave->link.connected) {
is_lower_up = TRUE; is_lower_up = TRUE;
} else { else {
NMPLookup lookup; NMPLookup lookup;
NMDedupMultiIter iter; NMDedupMultiIter iter;
const NMPlatformLink *link = NULL; 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) if ( (!potential_slave || potential_slave->link.ifindex != link->ifindex)
&& ignore_slave != obj && ignore_slave != obj
&& link->ifindex > 0 && nmp_cache_link_connected_for_slave (master->link.ifindex, obj)) {
&& link->master == master->link.ifindex
&& nmp_object_is_visible (obj)
&& link->connected) {
is_lower_up = TRUE; is_lower_up = TRUE;
break; break;
} }

View File

@@ -337,13 +337,22 @@ NMP_OBJECT_GET_TYPE (const NMPObject *obj)
return obj ? obj->_class->obj_type : NMP_OBJECT_TYPE_UNKNOWN; 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) \ #define NMP_OBJECT_CAST_IP4_ADDRESS(obj) \
({ \ ({ \
typeof (*(obj)) *_obj = (obj); \ typeof (*(obj)) *_obj = (obj); \
_nm_unused const NMPObject *_obj_type_check = _obj; \ _nm_unused const NMPObject *_obj_type_check = _obj; \
\ \
nm_assert (NMP_OBJECT_GET_TYPE (_obj) == NMP_OBJECT_TYPE_IP4_ADDRESS); \ nm_assert (!_obj || NMP_OBJECT_GET_TYPE (_obj) == NMP_OBJECT_TYPE_IP4_ADDRESS); \
&_obj->ip4_address; \ _obj ? &_obj->ip4_address : NULL; \
}) })
#define NMP_OBJECT_CAST_IP6_ADDRESS(obj) \ #define NMP_OBJECT_CAST_IP6_ADDRESS(obj) \
@@ -351,8 +360,8 @@ NMP_OBJECT_GET_TYPE (const NMPObject *obj)
typeof (*(obj)) *_obj = (obj); \ typeof (*(obj)) *_obj = (obj); \
_nm_unused const NMPObject *_obj_type_check = _obj; \ _nm_unused const NMPObject *_obj_type_check = _obj; \
\ \
nm_assert (NMP_OBJECT_GET_TYPE (_obj) == NMP_OBJECT_TYPE_IP6_ADDRESS); \ nm_assert (!_obj || NMP_OBJECT_GET_TYPE (_obj) == NMP_OBJECT_TYPE_IP6_ADDRESS); \
&_obj->ip6_address; \ _obj ? &_obj->ip6_address : NULL; \
}) })
#define NMP_OBJECT_CAST_IPX_ROUTE(obj) \ #define NMP_OBJECT_CAST_IPX_ROUTE(obj) \
@@ -541,6 +550,7 @@ const NMPObject *nmp_cache_lookup_link_full (const NMPCache *cache,
NMPObjectMatchFn match_fn, NMPObjectMatchFn match_fn,
gpointer user_data); 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); 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); const NMPObject *nmp_cache_link_connected_needs_toggle_by_ifindex (const NMPCache *cache, int master_ifindex, const NMPObject *potential_slave, const NMPObject *ignore_slave);

View File

@@ -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_up (NM_PLATFORM_GET, ifindex));
g_assert (!nm_platform_link_is_connected (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) { 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 /* 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 * 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)); g_assert (nm_platform_link_is_connected (NM_PLATFORM_GET, master));
accept_signals (link_changed, 1, 3); accept_signals (link_changed, 1, 3);
/* NM running, can cause additional change of addrgenmode */ /* NM running, can cause additional change of addrgenmode */
accept_signals (master_changed, 1, 2); accept_signals (master_changed, 0, 2);
/* Enslave again /* Enslave again
* *
@@ -327,7 +328,7 @@ test_slave (int master, int type, SignalData *master_changed)
ensure_no_signal (link_changed); ensure_no_signal (link_changed);
accept_signal (link_removed); accept_signal (link_removed);
} }
accept_signals (master_changed, 1, 2); accept_signals (master_changed, 0, 2);
ensure_no_signal (master_changed); ensure_no_signal (master_changed);