platform: promise that the link lnk is an immutable NMPObject and expose it

Expose internal lnk object and promise in the API that the object will
not be modified (which allows the user to ref it).
This commit is contained in:
Thomas Haller 2015-10-29 11:27:55 +01:00
parent f8fa4a0970
commit 4b1e1f8aab
8 changed files with 91 additions and 56 deletions

View file

@ -79,6 +79,8 @@ typedef struct _NMPlatformIP6Address NMPlatformIP6Address;
typedef struct _NMPlatformIP6Route NMPlatformIP6Route;
typedef struct _NMPlatformLink NMPlatformLink;
typedef struct _NMPObject NMPObject;
typedef enum {
/* Please don't interpret type numbers outside nm-platform and use functions
* like nm_platform_link_is_software() and nm_platform_supports_slaves().

View file

@ -27,6 +27,7 @@
#include <linux/rtnetlink.h>
#include "nm-utils.h"
#include "nmp-object.h"
#include "NetworkManagerUtils.h"
#include "nm-fake-platform.h"
#include "nm-default.h"
@ -74,8 +75,7 @@ typedef struct {
NMPlatformLink link;
char *udi;
NMPlatformLnkVlan lnk_vlan;
NMPlatformLnkInfiniband lnk_infiniband;
NMPObject *lnk;
struct in6_addr ip6_lladdr;
} NMFakePlatformLink;
@ -260,7 +260,7 @@ _nm_platform_link_get_by_address (NMPlatform *platform,
return NULL;
}
static gconstpointer
static const NMPObject *
link_get_lnk (NMPlatform *platform,
int ifindex,
NMLinkType link_type,
@ -273,17 +273,17 @@ link_get_lnk (NMPlatform *platform,
NM_SET_OUT (out_link, &device->link);
if (link_type != device->link.type)
if (!device->lnk)
return NULL;
switch (link_type) {
case NM_LINK_TYPE_VLAN:
return &device->lnk_vlan;
case NM_LINK_TYPE_INFINIBAND:
return &device->lnk_infiniband;
default:
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
@ -331,6 +331,8 @@ link_delete (NMPlatform *platform, int ifindex)
memcpy (&deleted_device, &device->link, sizeof (deleted_device));
memset (&device->link, 0, sizeof (device->link));
g_clear_pointer (&device->lnk, nmp_object_unref);
g_clear_pointer (&device->udi, g_free);
/* Remove addresses and routes which belong to the deleted interface */
for (i = 0; i < priv->ip4_addresses->len; i++) {
@ -671,8 +673,10 @@ vlan_add (NMPlatform *platform, const char *name, int parent, int vlan_id, guint
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_vlan.id = vlan_id;
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)
@ -707,9 +711,11 @@ infiniband_partition_add (NMPlatform *platform, int parent, int p_key, NMPlatfor
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_infiniband.p_key = p_key;
device->lnk_infiniband.mode = "datagram";
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;
@ -1381,6 +1387,7 @@ nm_fake_platform_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_array_unref (priv->links);
g_array_unref (priv->ip4_addresses);

View file

@ -3252,7 +3252,7 @@ _nm_platform_link_get_by_address (NMPlatform *platform,
/*****************************************************************************/
static gconstpointer
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);
@ -3262,34 +3262,14 @@ link_get_lnk (NMPlatform *platform, int ifindex, NMLinkType link_type, const NMP
NM_SET_OUT (out_link, &obj->link);
if (link_type != obj->link.type)
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;
switch (link_type) {
case NM_LINK_TYPE_GRE:
if (NMP_OBJECT_GET_TYPE (obj->_link.netlink.lnk) == NMP_OBJECT_TYPE_LNK_GRE)
return &obj->_link.netlink.lnk->lnk_gre;
break;
case NM_LINK_TYPE_INFINIBAND:
if (NMP_OBJECT_GET_TYPE (obj->_link.netlink.lnk) == NMP_OBJECT_TYPE_LNK_INFINIBAND)
return &obj->_link.netlink.lnk->lnk_infiniband;
break;
case NM_LINK_TYPE_MACVLAN:
if (NMP_OBJECT_GET_TYPE (obj->_link.netlink.lnk) == NMP_OBJECT_TYPE_LNK_MACVLAN)
return &obj->_link.netlink.lnk->lnk_macvlan;
break;
case NM_LINK_TYPE_VLAN:
if (NMP_OBJECT_GET_TYPE (obj->_link.netlink.lnk) == NMP_OBJECT_TYPE_LNK_VLAN)
return &obj->_link.netlink.lnk->lnk_vlan;
break;
case NM_LINK_TYPE_VXLAN:
if (NMP_OBJECT_GET_TYPE (obj->_link.netlink.lnk) == NMP_OBJECT_TYPE_LNK_VXLAN)
return &obj->_link.netlink.lnk->lnk_vxlan;
break;
default:
break;
}
return NULL;
return obj->_link.netlink.lnk;
}
/*****************************************************************************/

View file

@ -36,6 +36,7 @@
#include "nm-utils.h"
#include "nm-platform.h"
#include "nm-platform-utils.h"
#include "nmp-object.h"
#include "NetworkManagerUtils.h"
#include "nm-default.h"
#include "nm-enum-types.h"
@ -1369,7 +1370,29 @@ nm_platform_link_get_master (NMPlatform *self, int slave)
/*****************************************************************************/
gconstpointer
/**
* nm_platform_link_get_lnk:
* @self: the platform instance
* @ifindex: the link ifindex to lookup
* @link_type: filter by link-type.
* @out_link: (allow-none): returns the platform link instance
*
* If the function returns %NULL, that could mean that no such ifindex
* exists, of that the link has no lnk data. You can find that out
* by checking @out_link. @out_link will always be set if a link
* with @ifindex exists.
*
* If @link_type is %NM_LINK_TYPE_NONE, the function returns the lnk
* object if it is present. If you set link-type, you can be sure
* that only a link type of the matching type is returned (or %NULL).
*
* Returns: the internal link lnk object. The returned object
* is owned by the platform cache and must not be modified. Note
* however, that the object is guaranteed to be immutable, so
* you can savely take a reference and keep it for yourself
* (but don't modify it).
*/
const NMPObject *
nm_platform_link_get_lnk (NMPlatform *self, int ifindex, NMLinkType link_type, const NMPlatformLink **out_link)
{
_CHECK_SELF (self, klass, FALSE);
@ -1381,34 +1404,43 @@ nm_platform_link_get_lnk (NMPlatform *self, int ifindex, NMLinkType link_type, c
return klass->link_get_lnk (self, ifindex, link_type, out_link);
}
static gconstpointer
_link_get_lnk (NMPlatform *self, int ifindex, NMLinkType link_type, const NMPlatformLink **out_link)
{
const NMPObject *lnk;
lnk = nm_platform_link_get_lnk (self, ifindex, link_type, out_link);
return lnk ? &lnk->object : NULL;
}
const NMPlatformLnkGre *
nm_platform_link_get_lnk_gre (NMPlatform *self, int ifindex, const NMPlatformLink **out_link)
{
return nm_platform_link_get_lnk (self, ifindex, NM_LINK_TYPE_GRE, out_link);
return _link_get_lnk (self, ifindex, NM_LINK_TYPE_GRE, out_link);
}
const NMPlatformLnkInfiniband *
nm_platform_link_get_lnk_infiniband (NMPlatform *self, int ifindex, const NMPlatformLink **out_link)
{
return nm_platform_link_get_lnk (self, ifindex, NM_LINK_TYPE_INFINIBAND, out_link);
return _link_get_lnk (self, ifindex, NM_LINK_TYPE_INFINIBAND, out_link);
}
const NMPlatformLnkMacvlan *
nm_platform_link_get_lnk_macvlan (NMPlatform *self, int ifindex, const NMPlatformLink **out_link)
{
return nm_platform_link_get_lnk (self, ifindex, NM_LINK_TYPE_MACVLAN, out_link);
return _link_get_lnk (self, ifindex, NM_LINK_TYPE_MACVLAN, out_link);
}
const NMPlatformLnkVlan *
nm_platform_link_get_lnk_vlan (NMPlatform *self, int ifindex, const NMPlatformLink **out_link)
{
return nm_platform_link_get_lnk (self, ifindex, NM_LINK_TYPE_VLAN, out_link);
return _link_get_lnk (self, ifindex, NM_LINK_TYPE_VLAN, out_link);
}
const NMPlatformLnkVxlan *
nm_platform_link_get_lnk_vxlan (NMPlatform *self, int ifindex, const NMPlatformLink **out_link)
{
return nm_platform_link_get_lnk (self, ifindex, NM_LINK_TYPE_VXLAN, out_link);
return _link_get_lnk (self, ifindex, NM_LINK_TYPE_VXLAN, out_link);
}
/*****************************************************************************/

View file

@ -457,7 +457,7 @@ typedef struct {
const NMPlatformLink *(*link_get_by_ifname) (NMPlatform *platform, const char *ifname);
const NMPlatformLink *(*link_get_by_address) (NMPlatform *platform, gconstpointer address, size_t length);
gconstpointer (*link_get_lnk) (NMPlatform *platform, int ifindex, NMLinkType link_type, const NMPlatformLink **out_link);
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 *,
@ -696,7 +696,7 @@ char *nm_platform_master_get_option (NMPlatform *self, int ifindex, const char *
gboolean nm_platform_slave_set_option (NMPlatform *self, int ifindex, const char *option, const char *value);
char *nm_platform_slave_get_option (NMPlatform *self, int ifindex, const char *option);
gconstpointer nm_platform_link_get_lnk (NMPlatform *self, int ifindex, NMLinkType link_type, const NMPlatformLink **out_link);
const NMPObject *nm_platform_link_get_lnk (NMPlatform *self, int ifindex, NMLinkType link_type, const NMPlatformLink **out_link);
const NMPlatformLnkGre *nm_platform_link_get_lnk_gre (NMPlatform *self, int ifindex, const NMPlatformLink **out_link);
const NMPlatformLnkInfiniband *nm_platform_link_get_lnk_infiniband (NMPlatform *self, int ifindex, const NMPlatformLink **out_link);
const NMPlatformLnkMacvlan *nm_platform_link_get_lnk_macvlan (NMPlatform *self, int ifindex, const NMPlatformLink **out_link);

View file

@ -1891,6 +1891,7 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = {
.sizeof_data = sizeof (NMPObjectLnkGre),
.sizeof_public = sizeof (NMPlatformLnkGre),
.obj_type_name = "gre",
.lnk_link_type = NM_LINK_TYPE_GRE,
.cmd_plobj_to_string = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_lnk_gre_to_string,
.cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_gre_cmp,
},
@ -1899,6 +1900,7 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = {
.sizeof_data = sizeof (NMPObjectLnkInfiniband),
.sizeof_public = sizeof (NMPlatformLnkInfiniband),
.obj_type_name = "infiniband",
.lnk_link_type = NM_LINK_TYPE_INFINIBAND,
.cmd_plobj_to_string = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_lnk_infiniband_to_string,
.cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_infiniband_cmp,
},
@ -1907,6 +1909,7 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = {
.sizeof_data = sizeof (NMPObjectLnkMacvlan),
.sizeof_public = sizeof (NMPlatformLnkMacvlan),
.obj_type_name = "macvlan",
.lnk_link_type = NM_LINK_TYPE_MACVLAN,
.cmd_plobj_to_string = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_lnk_macvlan_to_string,
.cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_macvlan_cmp,
},
@ -1915,6 +1918,7 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = {
.sizeof_data = sizeof (NMPObjectLnkVlan),
.sizeof_public = sizeof (NMPlatformLnkVlan),
.obj_type_name = "vlan",
.lnk_link_type = NM_LINK_TYPE_VLAN,
.cmd_plobj_to_string = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_lnk_vlan_to_string,
.cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_vlan_cmp,
},
@ -1923,6 +1927,7 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = {
.sizeof_data = sizeof (NMPObjectLnkVxlan),
.sizeof_public = sizeof (NMPlatformLnkVxlan),
.obj_type_name = "vxlan",
.lnk_link_type = NM_LINK_TYPE_VXLAN,
.cmd_plobj_to_string = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_lnk_vxlan_to_string,
.cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_vxlan_cmp,
},

View file

@ -119,6 +119,9 @@ typedef struct {
const char *obj_type_name;
const char *signal_type;
/* Only for NMPObjectLnk* types. */
NMLinkType lnk_link_type;
/* returns %FALSE, if the obj type would never have an entry for index type @id_type. If @obj has an index,
* initialize @id and set @out_id to it. Otherwise, @out_id is NULL. */
gboolean (*cmd_obj_init_cache_id) (const NMPObject *obj, NMPCacheIdType id_type, NMPCacheId *id, const NMPCacheId **out_id);

View file

@ -1,5 +1,7 @@
#include "config.h"
#include "nmp-object.h"
#include "test-common.h"
#include "nm-test-utils.h"
@ -640,7 +642,7 @@ test_software_detect (gconstpointer user_data)
const TestAddSoftwareDetectData *test_data = user_data;
int ifindex, ifindex_parent;
const NMPlatformLink *plink;
gconstpointer plnk_void;
const NMPObject *lnk;
guint i_step;
int exit_code;
@ -708,15 +710,16 @@ test_software_detect (gconstpointer user_data)
nmtstp_link_set_updown (-1, ifindex, set_up);
}
plnk_void = nm_platform_link_get_lnk (NM_PLATFORM_GET, ifindex, test_data->link_type, &plink);
lnk = nm_platform_link_get_lnk (NM_PLATFORM_GET, ifindex, test_data->link_type, &plink);
g_assert (plink);
g_assert_cmpint (plink->ifindex, ==, ifindex);
g_assert (plnk_void);
g_assert (lnk);
switch (test_data->link_type) {
case NM_LINK_TYPE_GRE: {
const NMPlatformLnkGre *plnk = plnk_void;
const NMPlatformLnkGre *plnk = &lnk->lnk_gre;
g_assert (plnk == nm_platform_link_get_lnk_gre (NM_PLATFORM_GET, ifindex, NULL));
g_assert_cmpint (plnk->parent_ifindex, ==, 0);
g_assert_cmpint (plnk->input_flags, ==, 0);
g_assert_cmpint (plnk->output_flags, ==, 0);
@ -730,21 +733,24 @@ test_software_detect (gconstpointer user_data)
break;
}
case NM_LINK_TYPE_MACVLAN: {
const NMPlatformLnkMacvlan *plnk = plnk_void;
const NMPlatformLnkMacvlan *plnk = &lnk->lnk_macvlan;
g_assert (plnk == nm_platform_link_get_lnk_macvlan (NM_PLATFORM_GET, ifindex, NULL));
g_assert_cmpint (plnk->no_promisc, ==, FALSE);
g_assert_cmpstr (plnk->mode, ==, "vepa");
break;
}
case NM_LINK_TYPE_VLAN: {
const NMPlatformLnkVlan *plnk = plnk_void;
const NMPlatformLnkVlan *plnk = &lnk->lnk_vlan;
g_assert (plnk == nm_platform_link_get_lnk_vlan (NM_PLATFORM_GET, ifindex, NULL));
g_assert_cmpint (plnk->id, ==, 1242);
break;
}
case NM_LINK_TYPE_VXLAN: {
const NMPlatformLnkVxlan *plnk = plnk_void;
const NMPlatformLnkVxlan *plnk = &lnk->lnk_vxlan;
g_assert (plnk == nm_platform_link_get_lnk_vxlan (NM_PLATFORM_GET, ifindex, NULL));
g_assert_cmpint (plnk->parent_ifindex, !=, 0);
g_assert_cmpint (plnk->tos, ==, 0);
g_assert_cmpint (plnk->ttl, ==, 0);