mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2025-12-28 08:40:09 +01:00
platform: merge branch 'th/platform_refact_caching-bgo747981'
Refactor caching of NMPlatform and the way how to load objects via libnl/netlink. https://bugzilla.gnome.org/show_bug.cgi?id=747981 https://bugzilla.gnome.org/show_bug.cgi?id=747985 https://bugzilla.redhat.com/show_bug.cgi?id=1211133
This commit is contained in:
commit
35dcd8ac33
40 changed files with 6891 additions and 2521 deletions
|
|
@ -163,4 +163,53 @@ q_n##_quark (void) \
|
|||
}
|
||||
#endif
|
||||
|
||||
|
||||
static inline gboolean
|
||||
nm_g_hash_table_replace (GHashTable *hash, gpointer key, gpointer value)
|
||||
{
|
||||
/* glib 2.40 added a return value indicating whether the key already existed
|
||||
* (910191597a6c2e5d5d460e9ce9efb4f47d9cc63c). */
|
||||
#if GLIB_CHECK_VERSION(2, 40, 0)
|
||||
return g_hash_table_replace (hash, key, value);
|
||||
#else
|
||||
gboolean contained = g_hash_table_contains (hash, key);
|
||||
|
||||
g_hash_table_replace (hash, key, value);
|
||||
return !contained;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#if !GLIB_CHECK_VERSION(2, 40, 0) || defined (NM_GLIB_COMPAT_H_TEST)
|
||||
static inline void
|
||||
_nm_g_ptr_array_insert (GPtrArray *array,
|
||||
gint index_,
|
||||
gpointer data)
|
||||
{
|
||||
g_return_if_fail (array);
|
||||
g_return_if_fail (index_ >= -1);
|
||||
g_return_if_fail (index_ <= (gint) array->len);
|
||||
|
||||
g_ptr_array_add (array, data);
|
||||
|
||||
if (index_ != -1 && index_ != (gint) (array->len - 1)) {
|
||||
memmove (&(array->pdata[index_ + 1]),
|
||||
&(array->pdata[index_]),
|
||||
(array->len - index_ - 1) * sizeof (gpointer));
|
||||
array->pdata[index_] = data;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if !GLIB_CHECK_VERSION(2, 40, 0)
|
||||
#define g_ptr_array_insert(array, index, data) G_STMT_START { _nm_g_ptr_array_insert (array, index, data); } G_STMT_END
|
||||
#else
|
||||
#define g_ptr_array_insert(array, index, data) \
|
||||
G_STMT_START { \
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS \
|
||||
g_ptr_array_insert (array, index, data); \
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS \
|
||||
} G_STMT_END
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* __NM_GLIB_COMPAT_H__ */
|
||||
|
|
|
|||
|
|
@ -181,6 +181,23 @@ nm_clear_g_source (guint *id)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* Determine whether @x is a power of two (@x being an integer type).
|
||||
* For the special cases @x equals zero or one, it also returns true.
|
||||
* For negative @x, always returns FALSE. That only applies, is the data
|
||||
* type of @x is signed. */
|
||||
#define nm_utils_is_power_of_two(x) ({ \
|
||||
const typeof(x) __x = (x); \
|
||||
\
|
||||
((__x & (__x - 1)) == 0) && \
|
||||
/* Check if the value is negative. In that case, return FALSE.
|
||||
* The first expression is a compile time constant, depending on whether
|
||||
* the type is signed. The second expression is a clumsy way for (__x >= 0),
|
||||
* which causes a compiler warning for unsigned types. */ \
|
||||
( ( ((typeof(__x)) -1) > ((typeof(__x)) 0) ) || (__x > 0) || (__x == 0) ); \
|
||||
})
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* check if @flags has exactly one flag (@check) set. You should call this
|
||||
* only with @check being a compile time constant and a power of two. */
|
||||
#define NM_FLAGS_HAS(flags, check) \
|
||||
|
|
|
|||
|
|
@ -112,6 +112,8 @@ GPtrArray *_nm_utils_copy_array (const GPtrArray *array,
|
|||
GDestroyNotify free_func);
|
||||
GPtrArray *_nm_utils_copy_object_array (const GPtrArray *array);
|
||||
|
||||
gssize _nm_utils_ptrarray_find_first (gpointer *list, gssize len, gconstpointer needle);
|
||||
|
||||
gboolean _nm_utils_string_in_list (const char *str,
|
||||
const char **valid_strings);
|
||||
|
||||
|
|
|
|||
|
|
@ -631,6 +631,32 @@ _nm_utils_copy_object_array (const GPtrArray *array)
|
|||
return _nm_utils_copy_array (array, g_object_ref, g_object_unref);
|
||||
}
|
||||
|
||||
/* have @list of type 'gpointer *' instead of 'gconstpointer *' to
|
||||
* reduce the necessity for annoying const-casts. */
|
||||
gssize
|
||||
_nm_utils_ptrarray_find_first (gpointer *list, gssize len, gconstpointer needle)
|
||||
{
|
||||
gssize i;
|
||||
|
||||
if (len == 0)
|
||||
return -1;
|
||||
|
||||
if (len > 0) {
|
||||
g_return_val_if_fail (list, -1);
|
||||
for (i = 0; i < len; i++) {
|
||||
if (list[i] == needle)
|
||||
return i;
|
||||
}
|
||||
} else {
|
||||
g_return_val_if_fail (needle, -1);
|
||||
for (i = 0; list && list[i]; i++) {
|
||||
if (list[i] == needle)
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
GVariant *
|
||||
_nm_utils_bytes_to_dbus (const GValue *prop_value)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#define NM_GLIB_COMPAT_H_TEST
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <glib.h>
|
||||
|
|
@ -59,6 +61,7 @@
|
|||
#include "nm-setting-wireless-security.h"
|
||||
#include "nm-simple-connection.h"
|
||||
#include "nm-keyfile-internal.h"
|
||||
#include "nm-glib-compat.h"
|
||||
|
||||
#include "nm-test-utils.h"
|
||||
|
||||
|
|
@ -4358,6 +4361,128 @@ test_nm_utils_dns_option_find_idx (void)
|
|||
|
||||
/******************************************************************************/
|
||||
|
||||
enum TEST_IS_POWER_OF_TWP_ENUM_SIGNED {
|
||||
_DUMMY_1 = -1,
|
||||
};
|
||||
|
||||
enum TEST_IS_POWER_OF_TWP_ENUM_UNSIGNED {
|
||||
_DUMMY_2,
|
||||
};
|
||||
|
||||
enum TEST_IS_POWER_OF_TWP_ENUM_SIGNED_64 {
|
||||
_DUMMY_3 = (1LL << 40),
|
||||
};
|
||||
|
||||
enum TEST_IS_POWER_OF_TWP_ENUM_UNSIGNED_64 {
|
||||
_DUMMY_4a = -1,
|
||||
_DUMMY_4b = (1LL << 40),
|
||||
};
|
||||
|
||||
#define test_nm_utils_is_power_of_two_do(type, x, expect) \
|
||||
G_STMT_START { \
|
||||
typeof (x) x1 = (x); \
|
||||
type x2 = (type) x1; \
|
||||
\
|
||||
if (((typeof (x1)) x2) == x1 && (x2 > 0 || x2 == 0)) { \
|
||||
/* x2 equals @x, and is positive. Compare to @expect */ \
|
||||
g_assert_cmpint (expect, ==, nm_utils_is_power_of_two (x2)); \
|
||||
} else if (!(x2 > 0) && !(x2 == 0)) { \
|
||||
/* a (signed) negative value is always FALSE. */ \
|
||||
g_assert_cmpint (FALSE, ==, nm_utils_is_power_of_two (x2));\
|
||||
} \
|
||||
g_assert_cmpint (expect, ==, nm_utils_is_power_of_two (x1)); \
|
||||
} G_STMT_END
|
||||
|
||||
static void
|
||||
test_nm_utils_is_power_of_two ()
|
||||
{
|
||||
guint64 xyes, xno;
|
||||
gint i, j;
|
||||
GRand *rand = nmtst_get_rand ();
|
||||
int numbits;
|
||||
|
||||
for (i = -1; i < 64; i++) {
|
||||
|
||||
/* find a (positive) x which is a power of two. */
|
||||
if (i == -1)
|
||||
xyes = 0;
|
||||
else {
|
||||
xyes = (1LL << i);
|
||||
g_assert (xyes != 0);
|
||||
}
|
||||
|
||||
xno = xyes;
|
||||
if (xyes != 0) {
|
||||
again:
|
||||
/* Find another @xno, that is not a power of two. Do that,
|
||||
* by randomly setting bits. */
|
||||
numbits = g_rand_int_range (rand, 1, 65);
|
||||
while (xno != ~((guint64) 0) && numbits > 0) {
|
||||
guint64 v = (1LL << g_rand_int_range (rand, 0, 65));
|
||||
|
||||
if ((xno | v) != xno) {
|
||||
xno |= v;
|
||||
--numbits;
|
||||
}
|
||||
}
|
||||
if (xno == xyes)
|
||||
goto again;
|
||||
}
|
||||
|
||||
for (j = 0; j < 2; j++) {
|
||||
gboolean expect = j == 0;
|
||||
guint64 x = expect ? xyes : xno;
|
||||
|
||||
if (!expect && xno == 0)
|
||||
continue;
|
||||
|
||||
/* check if @x is as @expect, when casted to a certain data type. */
|
||||
test_nm_utils_is_power_of_two_do (gint8, x, expect);
|
||||
test_nm_utils_is_power_of_two_do (guint8, x, expect);
|
||||
test_nm_utils_is_power_of_two_do (gint16, x, expect);
|
||||
test_nm_utils_is_power_of_two_do (guint16, x, expect);
|
||||
test_nm_utils_is_power_of_two_do (gint32, x, expect);
|
||||
test_nm_utils_is_power_of_two_do (guint32, x, expect);
|
||||
test_nm_utils_is_power_of_two_do (gint64, x, expect);
|
||||
test_nm_utils_is_power_of_two_do (guint64, x, expect);
|
||||
test_nm_utils_is_power_of_two_do (char, x, expect);
|
||||
test_nm_utils_is_power_of_two_do (unsigned char, x, expect);
|
||||
test_nm_utils_is_power_of_two_do (signed char, x, expect);
|
||||
test_nm_utils_is_power_of_two_do (enum TEST_IS_POWER_OF_TWP_ENUM_SIGNED, x, expect);
|
||||
test_nm_utils_is_power_of_two_do (enum TEST_IS_POWER_OF_TWP_ENUM_UNSIGNED, x, expect);
|
||||
test_nm_utils_is_power_of_two_do (enum TEST_IS_POWER_OF_TWP_ENUM_SIGNED_64, x, expect);
|
||||
test_nm_utils_is_power_of_two_do (enum TEST_IS_POWER_OF_TWP_ENUM_UNSIGNED_64, x, expect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
static void
|
||||
test_g_ptr_array_insert (void)
|
||||
{
|
||||
/* this test only makes sense on a recent glib, where we compare our compat
|
||||
* with the original implementation. */
|
||||
#if GLIB_CHECK_VERSION(2, 40, 0)
|
||||
gs_unref_ptrarray GPtrArray *arr1 = g_ptr_array_new ();
|
||||
gs_unref_ptrarray GPtrArray *arr2 = g_ptr_array_new ();
|
||||
GRand *rand = nmtst_get_rand ();
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < 560; i++) {
|
||||
gint32 idx = g_rand_int_range (rand, -1, arr1->len + 1);
|
||||
|
||||
g_ptr_array_insert (arr1, idx, GINT_TO_POINTER (i));
|
||||
_nm_g_ptr_array_insert (arr2, idx, GINT_TO_POINTER (i));
|
||||
|
||||
g_assert_cmpint (arr1->len, ==, arr2->len);
|
||||
g_assert (memcmp (arr1->pdata, arr2->pdata, arr1->len * sizeof (gpointer)) == 0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
NMTST_DEFINE ();
|
||||
|
||||
int main (int argc, char **argv)
|
||||
|
|
@ -4459,6 +4584,8 @@ int main (int argc, char **argv)
|
|||
g_test_add_func ("/core/general/_nm_utils_uuid_generate_from_strings", test_nm_utils_uuid_generate_from_strings);
|
||||
|
||||
g_test_add_func ("/core/general/_nm_utils_ascii_str_to_int64", test_nm_utils_ascii_str_to_int64);
|
||||
g_test_add_func ("/core/general/nm_utils_is_power_of_two", test_nm_utils_is_power_of_two);
|
||||
g_test_add_func ("/core/general/_glib_compat_g_ptr_array_insert", test_g_ptr_array_insert);
|
||||
|
||||
g_test_add_func ("/core/general/_nm_utils_dns_option_validate", test_nm_utils_dns_option_validate);
|
||||
g_test_add_func ("/core/general/_nm_utils_dns_option_find_idx", test_nm_utils_dns_option_find_idx);
|
||||
|
|
|
|||
|
|
@ -227,6 +227,8 @@ nm_sources = \
|
|||
platform/nm-platform.h \
|
||||
platform/nm-platform-utils.c \
|
||||
platform/nm-platform-utils.h \
|
||||
platform/nmp-object.c \
|
||||
platform/nmp-object.h \
|
||||
platform/wifi/wifi-utils-nl80211.c \
|
||||
platform/wifi/wifi-utils-nl80211.h \
|
||||
platform/wifi/wifi-utils-private.h \
|
||||
|
|
@ -331,6 +333,8 @@ nm_sources = \
|
|||
nm-auth-utils.h \
|
||||
nm-manager.c \
|
||||
nm-manager.h \
|
||||
nm-multi-index.c \
|
||||
nm-multi-index.h \
|
||||
nm-policy.c \
|
||||
nm-policy.h \
|
||||
nm-properties-changed-signal.c \
|
||||
|
|
@ -473,6 +477,8 @@ libnm_iface_helper_la_SOURCES = \
|
|||
platform/nm-platform.h \
|
||||
platform/nm-platform-utils.c \
|
||||
platform/nm-platform-utils.h \
|
||||
platform/nmp-object.c \
|
||||
platform/nmp-object.h \
|
||||
platform/wifi/wifi-utils-nl80211.c \
|
||||
platform/wifi/wifi-utils-nl80211.h \
|
||||
platform/wifi/wifi-utils-private.h \
|
||||
|
|
@ -498,6 +504,8 @@ libnm_iface_helper_la_SOURCES = \
|
|||
nm-enum-types.h \
|
||||
nm-logging.c \
|
||||
nm-logging.h \
|
||||
nm-multi-index.c \
|
||||
nm-multi-index.h \
|
||||
NetworkManagerUtils.c \
|
||||
NetworkManagerUtils.h
|
||||
|
||||
|
|
|
|||
|
|
@ -352,7 +352,7 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *out_reason)
|
|||
_LOGD (LOGD_ADSL, "ATM setup successful");
|
||||
|
||||
/* otherwise we're good for stage3 */
|
||||
nm_platform_link_set_up (NM_PLATFORM_GET, priv->nas_ifindex);
|
||||
nm_platform_link_set_up (NM_PLATFORM_GET, priv->nas_ifindex, NULL);
|
||||
ret = NM_ACT_STAGE_RETURN_SUCCESS;
|
||||
|
||||
} else if (g_strcmp0 (protocol, NM_SETTING_ADSL_PROTOCOL_PPPOA) == 0) {
|
||||
|
|
|
|||
|
|
@ -571,16 +571,17 @@ create_virtual_device_for_connection (NMDeviceFactory *factory,
|
|||
GError **error)
|
||||
{
|
||||
const char *iface = nm_connection_get_interface_name (connection);
|
||||
NMPlatformError plerr;
|
||||
|
||||
g_assert (iface);
|
||||
|
||||
if ( !nm_platform_bond_add (NM_PLATFORM_GET, iface, NULL)
|
||||
&& nm_platform_get_error (NM_PLATFORM_GET) != NM_PLATFORM_ERROR_EXISTS) {
|
||||
plerr = nm_platform_bond_add (NM_PLATFORM_GET, iface, NULL);
|
||||
if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) {
|
||||
g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
|
||||
"Failed to create bond interface '%s' for '%s': %s",
|
||||
iface,
|
||||
nm_connection_get_id (connection),
|
||||
nm_platform_get_error_msg (NM_PLATFORM_GET));
|
||||
nm_platform_error_to_string (plerr));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -498,6 +498,7 @@ create_virtual_device_for_connection (NMDeviceFactory *factory,
|
|||
NMSettingBridge *s_bridge;
|
||||
const char *mac_address_str;
|
||||
guint8 mac_address[NM_UTILS_HWADDR_LEN_MAX];
|
||||
NMPlatformError plerr;
|
||||
|
||||
g_assert (iface);
|
||||
|
||||
|
|
@ -510,17 +511,17 @@ create_virtual_device_for_connection (NMDeviceFactory *factory,
|
|||
mac_address_str = NULL;
|
||||
}
|
||||
|
||||
if ( !nm_platform_bridge_add (NM_PLATFORM_GET,
|
||||
plerr = nm_platform_bridge_add (NM_PLATFORM_GET,
|
||||
iface,
|
||||
mac_address_str ? mac_address : NULL,
|
||||
mac_address_str ? ETH_ALEN : 0,
|
||||
NULL)
|
||||
&& nm_platform_get_error (NM_PLATFORM_GET) != NM_PLATFORM_ERROR_EXISTS) {
|
||||
NULL);
|
||||
if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) {
|
||||
g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
|
||||
"Failed to create bridge interface '%s' for '%s': %s",
|
||||
iface,
|
||||
nm_connection_get_id (connection),
|
||||
nm_platform_get_error_msg (NM_PLATFORM_GET));
|
||||
nm_platform_error_to_string (plerr));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@
|
|||
#include "nm-connection-provider.h"
|
||||
#include "nm-device-factory.h"
|
||||
#include "nm-core-internal.h"
|
||||
#include "NetworkManagerUtils.h"
|
||||
|
||||
#include "nm-device-ethernet-glue.h"
|
||||
|
||||
|
|
@ -151,28 +152,21 @@ static void
|
|||
_update_s390_subchannels (NMDeviceEthernet *self)
|
||||
{
|
||||
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
|
||||
GUdevClient *client;
|
||||
GUdevDevice *dev;
|
||||
GUdevDevice *parent = NULL;
|
||||
const char *parent_path, *item, *driver;
|
||||
const char *subsystems[] = { "net", NULL };
|
||||
const char *iface;
|
||||
int ifindex;
|
||||
GDir *dir;
|
||||
GError *error = NULL;
|
||||
|
||||
client = g_udev_client_new (subsystems);
|
||||
if (!client) {
|
||||
_LOGW (LOGD_DEVICE | LOGD_HW, "failed to initialize GUdev client");
|
||||
return;
|
||||
}
|
||||
|
||||
iface = nm_device_get_iface (NM_DEVICE (self));
|
||||
dev = iface ? g_udev_client_query_by_subsystem_and_name (client, "net", iface) : NULL;
|
||||
ifindex = nm_device_get_ifindex (NM_DEVICE (self));
|
||||
dev = (GUdevDevice *) nm_platform_link_get_udev_device (NM_PLATFORM_GET, ifindex);
|
||||
if (!dev) {
|
||||
_LOGW (LOGD_DEVICE | LOGD_HW, "failed to find device '%s' with udev",
|
||||
iface ? iface : "(null)");
|
||||
_LOGW (LOGD_DEVICE | LOGD_HW, "failed to find device %d '%s' with udev",
|
||||
ifindex, str_if_set (nm_device_get_iface (NM_DEVICE (self)), "(null)"));
|
||||
goto out;
|
||||
}
|
||||
g_object_ref (dev);
|
||||
|
||||
/* Try for the "ccwgroup" parent */
|
||||
parent = g_udev_device_get_parent_with_subsystem (dev, "ccwgroup", NULL);
|
||||
|
|
@ -244,7 +238,6 @@ out:
|
|||
g_object_unref (parent);
|
||||
if (dev)
|
||||
g_object_unref (dev);
|
||||
g_object_unref (client);
|
||||
}
|
||||
|
||||
static GObject*
|
||||
|
|
@ -1559,7 +1552,7 @@ link_changed (NMDevice *device, NMPlatformLink *info)
|
|||
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
|
||||
|
||||
NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->link_changed (device, info);
|
||||
if (!priv->subchan1 && info->udi)
|
||||
if (!priv->subchan1 && info->initialized)
|
||||
_update_s390_subchannels (self);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -326,6 +326,7 @@ create_virtual_device_for_connection (NMDeviceFactory *factory,
|
|||
NMSettingInfiniband *s_infiniband;
|
||||
int p_key, parent_ifindex;
|
||||
const char *iface;
|
||||
NMPlatformError plerr;
|
||||
|
||||
if (!NM_IS_DEVICE_INFINIBAND (parent)) {
|
||||
g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
|
||||
|
|
@ -342,13 +343,13 @@ create_virtual_device_for_connection (NMDeviceFactory *factory,
|
|||
parent_ifindex = nm_device_get_ifindex (parent);
|
||||
p_key = nm_setting_infiniband_get_p_key (s_infiniband);
|
||||
|
||||
if ( !nm_platform_infiniband_partition_add (NM_PLATFORM_GET, parent_ifindex, p_key, NULL)
|
||||
&& nm_platform_get_error (NM_PLATFORM_GET) != NM_PLATFORM_ERROR_EXISTS) {
|
||||
plerr = nm_platform_infiniband_partition_add (NM_PLATFORM_GET, parent_ifindex, p_key, NULL);
|
||||
if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) {
|
||||
g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
|
||||
"Failed to create InfiniBand P_Key interface '%s' for '%s': %s",
|
||||
iface,
|
||||
nm_connection_get_id (connection),
|
||||
nm_platform_get_error_msg (NM_PLATFORM_GET));
|
||||
nm_platform_error_to_string (plerr));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -656,6 +656,7 @@ create_virtual_device_for_connection (NMDeviceFactory *factory,
|
|||
NMDevice *device;
|
||||
NMSettingVlan *s_vlan;
|
||||
gs_free char *iface = NULL;
|
||||
NMPlatformError plerr;
|
||||
|
||||
if (!NM_IS_DEVICE (parent)) {
|
||||
g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
|
||||
|
|
@ -672,18 +673,18 @@ create_virtual_device_for_connection (NMDeviceFactory *factory,
|
|||
nm_setting_vlan_get_id (s_vlan));
|
||||
}
|
||||
|
||||
if ( !nm_platform_vlan_add (NM_PLATFORM_GET,
|
||||
plerr = nm_platform_vlan_add (NM_PLATFORM_GET,
|
||||
iface,
|
||||
nm_device_get_ifindex (parent),
|
||||
nm_setting_vlan_get_id (s_vlan),
|
||||
nm_setting_vlan_get_flags (s_vlan),
|
||||
NULL)
|
||||
&& nm_platform_get_error (NM_PLATFORM_GET) != NM_PLATFORM_ERROR_EXISTS) {
|
||||
NULL);
|
||||
if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) {
|
||||
g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
|
||||
"Failed to create VLAN interface '%s' for '%s': %s",
|
||||
iface,
|
||||
nm_connection_get_id (connection),
|
||||
nm_platform_get_error_msg (NM_PLATFORM_GET));
|
||||
nm_platform_error_to_string (plerr));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -598,7 +598,7 @@ nm_device_set_ip_iface (NMDevice *self, const char *iface)
|
|||
nm_platform_link_set_user_ipv6ll_enabled (NM_PLATFORM_GET, priv->ip_ifindex, TRUE);
|
||||
|
||||
if (!nm_platform_link_is_up (NM_PLATFORM_GET, priv->ip_ifindex))
|
||||
nm_platform_link_set_up (NM_PLATFORM_GET, priv->ip_ifindex);
|
||||
nm_platform_link_set_up (NM_PLATFORM_GET, priv->ip_ifindex, NULL);
|
||||
} else {
|
||||
/* Device IP interface must always be a kernel network interface */
|
||||
_LOGW (LOGD_HW, "failed to look up interface index");
|
||||
|
|
@ -1341,11 +1341,13 @@ device_link_changed (NMDevice *self, NMPlatformLink *info)
|
|||
NMUtilsIPv6IfaceId token_iid;
|
||||
gboolean ip_ifname_changed = FALSE;
|
||||
gboolean platform_unmanaged = FALSE;
|
||||
const char *udi;
|
||||
|
||||
if (info->udi && g_strcmp0 (info->udi, priv->udi)) {
|
||||
udi = nm_platform_link_get_udi (NM_PLATFORM_GET, info->ifindex);
|
||||
if (udi && g_strcmp0 (udi, priv->udi)) {
|
||||
/* Update UDI to what udev gives us */
|
||||
g_free (priv->udi);
|
||||
priv->udi = g_strdup (info->udi);
|
||||
priv->udi = g_strdup (udi);
|
||||
g_object_notify (G_OBJECT (self), NM_DEVICE_UDI);
|
||||
}
|
||||
|
||||
|
|
@ -1406,15 +1408,15 @@ device_link_changed (NMDevice *self, NMPlatformLink *info)
|
|||
if (ip_ifname_changed)
|
||||
update_for_ip_ifname_change (self);
|
||||
|
||||
if (priv->up != info->up) {
|
||||
priv->up = info->up;
|
||||
if (priv->up != NM_FLAGS_HAS (info->flags, IFF_UP)) {
|
||||
priv->up = NM_FLAGS_HAS (info->flags, IFF_UP);
|
||||
|
||||
/* Manage externally-created software interfaces only when they are IFF_UP */
|
||||
g_assert (priv->ifindex > 0);
|
||||
if (NM_DEVICE_GET_CLASS (self)->can_unmanaged_external_down (self)) {
|
||||
gboolean external_down = nm_device_get_unmanaged_flag (self, NM_UNMANAGED_EXTERNAL_DOWN);
|
||||
|
||||
if (external_down && info->up) {
|
||||
if (external_down && NM_FLAGS_HAS (info->flags, IFF_UP)) {
|
||||
if (nm_device_get_state (self) < NM_DEVICE_STATE_DISCONNECTED) {
|
||||
/* Ensure the assume check is queued before any queued state changes
|
||||
* from the transition to UNAVAILABLE.
|
||||
|
|
@ -1437,7 +1439,7 @@ device_link_changed (NMDevice *self, NMPlatformLink *info)
|
|||
*/
|
||||
priv->unmanaged_flags &= ~NM_UNMANAGED_EXTERNAL_DOWN;
|
||||
}
|
||||
} else if (!external_down && !info->up && nm_device_get_state (self) <= NM_DEVICE_STATE_DISCONNECTED) {
|
||||
} else if (!external_down && !NM_FLAGS_HAS (info->flags, IFF_UP) && nm_device_get_state (self) <= NM_DEVICE_STATE_DISCONNECTED) {
|
||||
/* If the device is already disconnected and is set !IFF_UP,
|
||||
* unmanage it.
|
||||
*/
|
||||
|
|
@ -4721,8 +4723,7 @@ set_nm_ipv6ll (NMDevice *self, gboolean enable)
|
|||
const char *detail = enable ? "enable" : "disable";
|
||||
|
||||
_LOGD (LOGD_IP6, "will %s userland IPv6LL", detail);
|
||||
if ( !nm_platform_link_set_user_ipv6ll_enabled (NM_PLATFORM_GET, ifindex, enable)
|
||||
&& nm_platform_get_error (NM_PLATFORM_GET) != NM_PLATFORM_ERROR_NOT_FOUND)
|
||||
if (!nm_platform_link_set_user_ipv6ll_enabled (NM_PLATFORM_GET, ifindex, enable))
|
||||
_LOGW (LOGD_IP6, "failed to %s userspace IPv6LL address handling", detail);
|
||||
|
||||
if (enable) {
|
||||
|
|
@ -5526,7 +5527,7 @@ nm_device_activate_ip4_config_commit (gpointer user_data)
|
|||
/* Interface must be IFF_UP before IP config can be applied */
|
||||
ip_ifindex = nm_device_get_ip_ifindex (self);
|
||||
if (!nm_platform_link_is_up (NM_PLATFORM_GET, ip_ifindex) && !nm_device_uses_assumed_connection (self)) {
|
||||
nm_platform_link_set_up (NM_PLATFORM_GET, ip_ifindex);
|
||||
nm_platform_link_set_up (NM_PLATFORM_GET, ip_ifindex, NULL);
|
||||
if (!nm_platform_link_is_up (NM_PLATFORM_GET, ip_ifindex))
|
||||
_LOGW (LOGD_DEVICE, "interface %s not up for IP configuration", nm_device_get_ip_iface (self));
|
||||
}
|
||||
|
|
@ -5647,7 +5648,7 @@ nm_device_activate_ip6_config_commit (gpointer user_data)
|
|||
/* Interface must be IFF_UP before IP config can be applied */
|
||||
ip_ifindex = nm_device_get_ip_ifindex (self);
|
||||
if (!nm_platform_link_is_up (NM_PLATFORM_GET, ip_ifindex) && !nm_device_uses_assumed_connection (self)) {
|
||||
nm_platform_link_set_up (NM_PLATFORM_GET, ip_ifindex);
|
||||
nm_platform_link_set_up (NM_PLATFORM_GET, ip_ifindex, NULL);
|
||||
if (!nm_platform_link_is_up (NM_PLATFORM_GET, ip_ifindex))
|
||||
_LOGW (LOGD_DEVICE, "interface %s not up for IP configuration", nm_device_get_ip_iface (self));
|
||||
}
|
||||
|
|
@ -6791,9 +6792,7 @@ bring_up (NMDevice *self, gboolean *no_firmware)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
result = nm_platform_link_set_up (NM_PLATFORM_GET, ifindex);
|
||||
if (no_firmware)
|
||||
*no_firmware = nm_platform_get_error (NM_PLATFORM_GET) == NM_PLATFORM_ERROR_NO_FIRMWARE;
|
||||
result = nm_platform_link_set_up (NM_PLATFORM_GET, ifindex, no_firmware);
|
||||
|
||||
/* Store carrier immediately. */
|
||||
if (result && nm_device_has_capability (self, NM_DEVICE_CAP_CARRIER_DETECT))
|
||||
|
|
@ -8772,8 +8771,7 @@ constructed (GObject *object)
|
|||
priv->perm_hw_addr);
|
||||
} else {
|
||||
/* Fall back to current address */
|
||||
_LOGD (LOGD_HW | LOGD_ETHER, "unable to read permanent MAC address (error %d)",
|
||||
nm_platform_get_error (NM_PLATFORM_GET));
|
||||
_LOGD (LOGD_HW | LOGD_ETHER, "unable to read permanent MAC address");
|
||||
priv->perm_hw_addr = g_strdup (priv->hw_addr);
|
||||
}
|
||||
}
|
||||
|
|
@ -8938,11 +8936,11 @@ set_property (GObject *object, guint prop_id,
|
|||
platform_device = g_value_get_pointer (value);
|
||||
if (platform_device) {
|
||||
g_free (priv->udi);
|
||||
priv->udi = g_strdup (platform_device->udi);
|
||||
priv->udi = g_strdup (nm_platform_link_get_udi (NM_PLATFORM_GET, platform_device->ifindex));
|
||||
g_free (priv->iface);
|
||||
priv->iface = g_strdup (platform_device->name);
|
||||
priv->ifindex = platform_device->ifindex;
|
||||
priv->up = platform_device->up;
|
||||
priv->up = NM_FLAGS_HAS (platform_device->flags, IFF_UP);
|
||||
g_free (priv->driver);
|
||||
priv->driver = g_strdup (platform_device->driver);
|
||||
priv->platform_link_initialized = platform_device->initialized;
|
||||
|
|
|
|||
|
|
@ -689,16 +689,17 @@ NMDevice *
|
|||
nm_device_team_new_for_connection (NMConnection *connection, GError **error)
|
||||
{
|
||||
const char *iface = nm_connection_get_interface_name (connection);
|
||||
NMPlatformError plerr;
|
||||
|
||||
g_assert (iface);
|
||||
|
||||
if ( !nm_platform_team_add (NM_PLATFORM_GET, iface, NULL)
|
||||
&& nm_platform_get_error (NM_PLATFORM_GET) != NM_PLATFORM_ERROR_EXISTS) {
|
||||
plerr = nm_platform_team_add (NM_PLATFORM_GET, iface, NULL);
|
||||
if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) {
|
||||
g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
|
||||
"Failed to create team master interface '%s' for '%s': %s",
|
||||
iface,
|
||||
nm_connection_get_id (connection),
|
||||
nm_platform_get_error_msg (NM_PLATFORM_GET));
|
||||
nm_platform_error_to_string (plerr));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -477,7 +477,7 @@ main (int argc, char *argv[])
|
|||
* physical interfaces.
|
||||
*/
|
||||
nm_log_dbg (LOGD_CORE, "setting up local loopback");
|
||||
nm_platform_link_set_up (NM_PLATFORM_GET, 1);
|
||||
nm_platform_link_set_up (NM_PLATFORM_GET, 1, NULL);
|
||||
|
||||
success = TRUE;
|
||||
|
||||
|
|
|
|||
441
src/nm-multi-index.c
Normal file
441
src/nm-multi-index.c
Normal file
|
|
@ -0,0 +1,441 @@
|
|||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
||||
/* NetworkManager -- Network link manager
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Copyright (C) 2015 Red Hat, Inc.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "nm-multi-index.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "nm-glib-compat.h"
|
||||
#include "nm-macros-internal.h"
|
||||
|
||||
|
||||
struct NMMultiIndex {
|
||||
NMMultiIndexFuncEqual equal_fcn;
|
||||
NMMultiIndexFuncClone clone_fcn;
|
||||
GHashTable *hash;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
GHashTable *index;
|
||||
gpointer *values;
|
||||
} ValuesData;
|
||||
|
||||
/******************************************************************************************/
|
||||
|
||||
static ValuesData *
|
||||
_values_data_create ()
|
||||
{
|
||||
ValuesData *values_data;
|
||||
|
||||
values_data = g_slice_new (ValuesData);
|
||||
values_data->index = g_hash_table_new (NULL, NULL);
|
||||
values_data->values = NULL;
|
||||
return values_data;
|
||||
}
|
||||
|
||||
static void
|
||||
_values_data_destroy (ValuesData *values_data)
|
||||
{
|
||||
if (values_data) {
|
||||
g_free (values_data->values);
|
||||
g_hash_table_unref (values_data->index);
|
||||
g_slice_free (ValuesData, values_data);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_values_data_populate_array (ValuesData *values_data)
|
||||
{
|
||||
guint i, len;
|
||||
gpointer *values;
|
||||
GHashTableIter iter;
|
||||
|
||||
nm_assert (values_data);
|
||||
nm_assert (values_data->index && g_hash_table_size (values_data->index) > 0);
|
||||
|
||||
if (values_data->values)
|
||||
return;
|
||||
|
||||
len = g_hash_table_size (values_data->index);
|
||||
values = g_new (gpointer, len + 1);
|
||||
|
||||
g_hash_table_iter_init (&iter, values_data->index);
|
||||
for (i = 0; g_hash_table_iter_next (&iter, &values[i], NULL); i++)
|
||||
nm_assert (i < len);
|
||||
nm_assert (i == len);
|
||||
values[i] = NULL;
|
||||
|
||||
values_data->values = values;
|
||||
}
|
||||
|
||||
/******************************************************************************************/
|
||||
|
||||
/**
|
||||
* nm_multi_index_lookup():
|
||||
* @index:
|
||||
* @id:
|
||||
* @out_len: (allow-none): output the number of values
|
||||
* that are returned.
|
||||
*
|
||||
* Returns: (transfer-none): %NULL if there are no values
|
||||
* or a %NULL terminated array of pointers.
|
||||
*/
|
||||
void *const*
|
||||
nm_multi_index_lookup (const NMMultiIndex *index,
|
||||
const NMMultiIndexId *id,
|
||||
guint *out_len)
|
||||
{
|
||||
ValuesData *values_data;
|
||||
|
||||
g_return_val_if_fail (index, NULL);
|
||||
g_return_val_if_fail (id, NULL);
|
||||
|
||||
values_data = g_hash_table_lookup (index->hash, id);
|
||||
if (!values_data) {
|
||||
if (out_len)
|
||||
*out_len = 0;
|
||||
return NULL;
|
||||
}
|
||||
_values_data_populate_array (values_data);
|
||||
if (out_len)
|
||||
*out_len = g_hash_table_size (values_data->index);
|
||||
return values_data->values;
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_multi_index_contains (const NMMultiIndex *index,
|
||||
const NMMultiIndexId *id,
|
||||
gconstpointer value)
|
||||
{
|
||||
ValuesData *values_data;
|
||||
|
||||
g_return_val_if_fail (index, FALSE);
|
||||
g_return_val_if_fail (id, FALSE);
|
||||
g_return_val_if_fail (value, FALSE);
|
||||
|
||||
values_data = g_hash_table_lookup (index->hash, id);
|
||||
return values_data
|
||||
&& g_hash_table_contains (values_data->index, value);
|
||||
}
|
||||
|
||||
const NMMultiIndexId *
|
||||
nm_multi_index_lookup_first_by_value (const NMMultiIndex *index,
|
||||
gconstpointer value)
|
||||
{
|
||||
GHashTableIter iter;
|
||||
const NMMultiIndexId *id;
|
||||
ValuesData *values_data;
|
||||
|
||||
g_return_val_if_fail (index, NULL);
|
||||
g_return_val_if_fail (value, NULL);
|
||||
|
||||
/* reverse-lookup needs to iterate over all hash tables. It should
|
||||
* still be fairly quick, if the number of hash tables is small.
|
||||
* There is no O(1) reverse lookup implemented, because this access
|
||||
* pattern is not what NMMultiIndex is here for.
|
||||
* You are supposed to use NMMultiIndex by always knowing which @id
|
||||
* a @value has.
|
||||
*/
|
||||
|
||||
g_hash_table_iter_init (&iter, index->hash);
|
||||
while (g_hash_table_iter_next (&iter, (gpointer *) &id, (gpointer *) &values_data)) {
|
||||
if (g_hash_table_contains (values_data->index, value))
|
||||
return id;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
nm_multi_index_foreach (const NMMultiIndex *index,
|
||||
gconstpointer value,
|
||||
NMMultiIndexFuncForeach foreach_func,
|
||||
gpointer user_data)
|
||||
{
|
||||
GHashTableIter iter;
|
||||
const NMMultiIndexId *id;
|
||||
ValuesData *values_data;
|
||||
|
||||
g_return_if_fail (index);
|
||||
g_return_if_fail (foreach_func);
|
||||
|
||||
g_hash_table_iter_init (&iter, index->hash);
|
||||
while (g_hash_table_iter_next (&iter, (gpointer *) &id, (gpointer *) &values_data)) {
|
||||
if ( value
|
||||
&& !g_hash_table_contains (values_data->index, value))
|
||||
continue;
|
||||
|
||||
_values_data_populate_array (values_data);
|
||||
if (!foreach_func (id, values_data->values, g_hash_table_size (values_data->index), user_data))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nm_multi_index_iter_init (NMMultiIndexIter *iter,
|
||||
const NMMultiIndex *index,
|
||||
gconstpointer value)
|
||||
{
|
||||
g_return_if_fail (index);
|
||||
g_return_if_fail (iter);
|
||||
|
||||
g_hash_table_iter_init (&iter->_iter, index->hash);
|
||||
iter->_index = index;
|
||||
iter->_value = value;
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_multi_index_iter_next (NMMultiIndexIter *iter,
|
||||
const NMMultiIndexId **out_id,
|
||||
void *const**out_values,
|
||||
guint *out_len)
|
||||
{
|
||||
const NMMultiIndexId *id;
|
||||
ValuesData *values_data;
|
||||
|
||||
g_return_val_if_fail (iter, FALSE);
|
||||
|
||||
while (g_hash_table_iter_next (&iter->_iter, (gpointer *) &id, (gpointer *) &values_data)) {
|
||||
if ( !iter->_value
|
||||
|| g_hash_table_contains (values_data->index, iter->_value)) {
|
||||
_values_data_populate_array (values_data);
|
||||
if (out_id)
|
||||
*out_id = id;
|
||||
if (out_values)
|
||||
*out_values = values_data->values;
|
||||
if (out_len)
|
||||
*out_len = g_hash_table_size (values_data->index);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/******************************************************************************************/
|
||||
|
||||
void
|
||||
nm_multi_index_id_iter_init (NMMultiIndexIdIter *iter,
|
||||
const NMMultiIndex *index,
|
||||
const NMMultiIndexId *id)
|
||||
{
|
||||
ValuesData *values_data;
|
||||
|
||||
g_return_if_fail (index);
|
||||
g_return_if_fail (iter);
|
||||
g_return_if_fail (id);
|
||||
|
||||
values_data = g_hash_table_lookup (index->hash, id);
|
||||
if (!values_data)
|
||||
iter->_state = 1;
|
||||
else {
|
||||
iter->_state = 0;
|
||||
g_hash_table_iter_init (&iter->_iter, values_data->index);
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_multi_index_id_iter_next (NMMultiIndexIdIter *iter,
|
||||
void **out_value)
|
||||
{
|
||||
g_return_val_if_fail (iter, FALSE);
|
||||
g_return_val_if_fail (iter->_state <= 1, FALSE);
|
||||
|
||||
if (iter->_state == 0)
|
||||
return g_hash_table_iter_next (&iter->_iter, out_value, NULL);
|
||||
else {
|
||||
iter->_state = 2;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************************/
|
||||
|
||||
static gboolean
|
||||
_do_add (NMMultiIndex *index,
|
||||
const NMMultiIndexId *id,
|
||||
gconstpointer value)
|
||||
{
|
||||
ValuesData *values_data;
|
||||
|
||||
values_data = g_hash_table_lookup (index->hash, id);
|
||||
if (!values_data) {
|
||||
NMMultiIndexId *id_new;
|
||||
|
||||
/* Contrary to GHashTable, we don't take ownership of the @id that was
|
||||
* provided to nm_multi_index_add(). Instead we clone it via @clone_fcn
|
||||
* when needed.
|
||||
*
|
||||
* The reason is, that we expect in most cases that there exists
|
||||
* already a @id so that we don't need ownership of it (or clone it).
|
||||
* By doing this, the caller can pass a stack allocated @id or
|
||||
* reuse the @id for other insertions.
|
||||
*/
|
||||
id_new = index->clone_fcn (id);
|
||||
if (!id_new)
|
||||
g_return_val_if_reached (FALSE);
|
||||
|
||||
values_data = _values_data_create ();
|
||||
g_hash_table_replace (values_data->index, (gpointer) value, (gpointer) value);
|
||||
|
||||
g_hash_table_insert (index->hash, id_new, values_data);
|
||||
} else {
|
||||
if (!nm_g_hash_table_replace (values_data->index, (gpointer) value, (gpointer) value))
|
||||
return FALSE;
|
||||
g_clear_pointer (&values_data->values, g_free);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_do_remove (NMMultiIndex *index,
|
||||
const NMMultiIndexId *id,
|
||||
gconstpointer value)
|
||||
{
|
||||
ValuesData *values_data;
|
||||
|
||||
values_data = g_hash_table_lookup (index->hash, id);
|
||||
if (!values_data)
|
||||
return FALSE;
|
||||
|
||||
if (!g_hash_table_remove (values_data->index, value))
|
||||
return FALSE;
|
||||
|
||||
if (g_hash_table_size (values_data->index) == 0)
|
||||
g_hash_table_remove (index->hash, id);
|
||||
else
|
||||
g_clear_pointer (&values_data->values, g_free);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_multi_index_add (NMMultiIndex *index,
|
||||
const NMMultiIndexId *id,
|
||||
gconstpointer value)
|
||||
{
|
||||
g_return_val_if_fail (index, FALSE);
|
||||
g_return_val_if_fail (id, FALSE);
|
||||
g_return_val_if_fail (value, FALSE);
|
||||
|
||||
return _do_add (index, id, value);
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_multi_index_remove (NMMultiIndex *index,
|
||||
const NMMultiIndexId *id,
|
||||
gconstpointer value)
|
||||
{
|
||||
g_return_val_if_fail (index, FALSE);
|
||||
g_return_val_if_fail (value, FALSE);
|
||||
|
||||
if (!id)
|
||||
g_return_val_if_reached (FALSE);
|
||||
return _do_remove (index, id, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_multi_index_move:
|
||||
* @index:
|
||||
* @id_old: (allow-none): remove @value at @id_old
|
||||
* @id_new: (allow-none): add @value under @id_new
|
||||
* @value: the value to add
|
||||
*
|
||||
* Similar to a remove(), followed by an add(). The difference
|
||||
* is, that we allow %NULL for both @id_old and @id_new.
|
||||
* And the return value indicates whether @value was successfully
|
||||
* removed *and* added.
|
||||
*
|
||||
* Returns: %TRUE, if the value was removed from @id_old and added
|
||||
* as %id_new. %FALSE could mean, that @value was not added to @id_old
|
||||
* before, or that that @value was already part of @id_new. */
|
||||
gboolean
|
||||
nm_multi_index_move (NMMultiIndex *index,
|
||||
const NMMultiIndexId *id_old,
|
||||
const NMMultiIndexId *id_new,
|
||||
gconstpointer value)
|
||||
{
|
||||
g_return_val_if_fail (index, FALSE);
|
||||
g_return_val_if_fail (value, FALSE);
|
||||
|
||||
if (!id_old && !id_new) {
|
||||
/* nothing to do, @value was and is not in @index. */
|
||||
return TRUE;
|
||||
} if (!id_old) {
|
||||
/* add @value to @index with @id_new */
|
||||
return _do_add (index, id_new, value);
|
||||
} else if (!id_new) {
|
||||
/* remove @value from @index with @id_old */
|
||||
return _do_remove (index, id_old, value);
|
||||
} else if (index->equal_fcn (id_old, id_new)) {
|
||||
if (_do_add (index, id_new, value)) {
|
||||
/* we would expect, that @value is already in @index,
|
||||
* Return %FALSE, if it wasn't. */
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
} else {
|
||||
gboolean did_remove;
|
||||
|
||||
did_remove = _do_remove (index, id_old, value);
|
||||
return _do_add (index, id_new, value) && did_remove;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************************/
|
||||
|
||||
guint
|
||||
nm_multi_index_get_num_groups (const NMMultiIndex *index)
|
||||
{
|
||||
g_return_val_if_fail (index, 0);
|
||||
return g_hash_table_size (index->hash);
|
||||
}
|
||||
|
||||
NMMultiIndex *
|
||||
nm_multi_index_new (NMMultiIndexFuncHash hash_fcn,
|
||||
NMMultiIndexFuncEqual equal_fcn,
|
||||
NMMultiIndexFuncClone clone_fcn,
|
||||
NMMultiIndexFuncDestroy destroy_fcn)
|
||||
{
|
||||
NMMultiIndex *index;
|
||||
|
||||
g_return_val_if_fail (hash_fcn, NULL);
|
||||
g_return_val_if_fail (equal_fcn, NULL);
|
||||
g_return_val_if_fail (clone_fcn, NULL);
|
||||
g_return_val_if_fail (destroy_fcn, NULL);
|
||||
|
||||
index = g_new (NMMultiIndex, 1);
|
||||
index->equal_fcn = equal_fcn;
|
||||
index->clone_fcn = clone_fcn;
|
||||
|
||||
index->hash = g_hash_table_new_full ((GHashFunc) hash_fcn,
|
||||
(GEqualFunc) equal_fcn,
|
||||
(GDestroyNotify) destroy_fcn,
|
||||
(GDestroyNotify) _values_data_destroy);
|
||||
return index;
|
||||
}
|
||||
|
||||
void
|
||||
nm_multi_index_free (NMMultiIndex *index)
|
||||
{
|
||||
g_return_if_fail (index);
|
||||
g_hash_table_unref (index->hash);
|
||||
g_free (index);
|
||||
}
|
||||
|
||||
109
src/nm-multi-index.h
Normal file
109
src/nm-multi-index.h
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
||||
/* NetworkManager -- Network link manager
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Copyright (C) 2015 Red Hat, Inc.
|
||||
*/
|
||||
|
||||
#ifndef __NM_MULTI_INDEX__
|
||||
#define __NM_MULTI_INDEX__
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
||||
typedef struct {
|
||||
char _dummy;
|
||||
} NMMultiIndexId;
|
||||
|
||||
typedef struct NMMultiIndex NMMultiIndex;
|
||||
|
||||
typedef struct {
|
||||
GHashTableIter _iter;
|
||||
const NMMultiIndex *_index;
|
||||
gconstpointer _value;
|
||||
} NMMultiIndexIter;
|
||||
|
||||
typedef struct {
|
||||
GHashTableIter _iter;
|
||||
guint _state;
|
||||
} NMMultiIndexIdIter;
|
||||
|
||||
typedef gboolean (*NMMultiIndexFuncEqual) (const NMMultiIndexId *id_a, const NMMultiIndexId *id_b);
|
||||
typedef guint (*NMMultiIndexFuncHash) (const NMMultiIndexId *id);
|
||||
typedef NMMultiIndexId *(*NMMultiIndexFuncClone) (const NMMultiIndexId *id);
|
||||
typedef void (*NMMultiIndexFuncDestroy) (NMMultiIndexId *id);
|
||||
|
||||
typedef gboolean (*NMMultiIndexFuncForeach) (const NMMultiIndexId *id, void *const* values, guint len, gpointer user_data);
|
||||
|
||||
|
||||
NMMultiIndex *nm_multi_index_new (NMMultiIndexFuncHash hash_fcn,
|
||||
NMMultiIndexFuncEqual equal_fcn,
|
||||
NMMultiIndexFuncClone clone_fcn,
|
||||
NMMultiIndexFuncDestroy destroy_fcn);
|
||||
|
||||
void nm_multi_index_free (NMMultiIndex *index);
|
||||
|
||||
gboolean nm_multi_index_add (NMMultiIndex *index,
|
||||
const NMMultiIndexId *id,
|
||||
gconstpointer value);
|
||||
|
||||
gboolean nm_multi_index_remove (NMMultiIndex *index,
|
||||
const NMMultiIndexId *id,
|
||||
gconstpointer value);
|
||||
|
||||
gboolean nm_multi_index_move (NMMultiIndex *index,
|
||||
const NMMultiIndexId *id_old,
|
||||
const NMMultiIndexId *id_new,
|
||||
gconstpointer value);
|
||||
|
||||
guint nm_multi_index_get_num_groups (const NMMultiIndex *index);
|
||||
|
||||
void *const*nm_multi_index_lookup (const NMMultiIndex *index,
|
||||
const NMMultiIndexId *id,
|
||||
guint *out_len);
|
||||
|
||||
gboolean nm_multi_index_contains (const NMMultiIndex *index,
|
||||
const NMMultiIndexId *id,
|
||||
gconstpointer value);
|
||||
|
||||
const NMMultiIndexId *nm_multi_index_lookup_first_by_value (const NMMultiIndex *index,
|
||||
gconstpointer value);
|
||||
|
||||
void nm_multi_index_foreach (const NMMultiIndex *index,
|
||||
gconstpointer value,
|
||||
NMMultiIndexFuncForeach foreach_func,
|
||||
gpointer user_data);
|
||||
|
||||
void nm_multi_index_iter_init (NMMultiIndexIter *iter,
|
||||
const NMMultiIndex *index,
|
||||
gconstpointer value);
|
||||
gboolean nm_multi_index_iter_next (NMMultiIndexIter *iter,
|
||||
const NMMultiIndexId **out_id,
|
||||
void *const**out_values,
|
||||
guint *out_len);
|
||||
|
||||
void nm_multi_index_id_iter_init (NMMultiIndexIdIter *iter,
|
||||
const NMMultiIndex *index,
|
||||
const NMMultiIndexId *id);
|
||||
gboolean nm_multi_index_id_iter_next (NMMultiIndexIdIter *iter,
|
||||
void **out_value);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __NM_MULTI_INDEX__ */
|
||||
|
||||
|
|
@ -51,6 +51,13 @@ typedef struct _NMSleepMonitor NMSleepMonitor;
|
|||
typedef enum {
|
||||
/* In priority order; higher number == higher priority */
|
||||
NM_IP_CONFIG_SOURCE_UNKNOWN,
|
||||
|
||||
/* platform internal flag used to mark routes with RTM_F_CLONED. */
|
||||
_NM_IP_CONFIG_SOURCE_RTM_F_CLONED,
|
||||
|
||||
/* platform internal flag used to mark routes with protocol RTPROT_KERNEL. */
|
||||
_NM_IP_CONFIG_SOURCE_RTPROT_KERNEL,
|
||||
|
||||
NM_IP_CONFIG_SOURCE_KERNEL,
|
||||
NM_IP_CONFIG_SOURCE_SHARED,
|
||||
NM_IP_CONFIG_SOURCE_IP4LL,
|
||||
|
|
|
|||
|
|
@ -24,12 +24,16 @@
|
|||
#include <unistd.h>
|
||||
#include <netinet/icmp6.h>
|
||||
#include <netinet/in.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
|
||||
#include "gsystem-local-alloc.h"
|
||||
#include "nm-utils.h"
|
||||
#include "NetworkManagerUtils.h"
|
||||
#include "nm-fake-platform.h"
|
||||
#include "nm-logging.h"
|
||||
|
||||
#include "nm-test-utils.h"
|
||||
|
||||
#define debug(format, ...) nm_log_dbg (LOGD_PLATFORM, format, __VA_ARGS__)
|
||||
|
||||
typedef struct {
|
||||
|
|
@ -48,6 +52,7 @@ typedef struct {
|
|||
GBytes *address;
|
||||
int vlan_id;
|
||||
int ib_p_key;
|
||||
struct in6_addr ip6_lladdr;
|
||||
} NMFakePlatformLink;
|
||||
|
||||
#define NM_FAKE_PLATFORM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_FAKE_PLATFORM, NMFakePlatformPrivate))
|
||||
|
|
@ -56,6 +61,15 @@ G_DEFINE_TYPE (NMFakePlatform, nm_fake_platform, NM_TYPE_PLATFORM)
|
|||
|
||||
/******************************************************************/
|
||||
|
||||
static void link_changed (NMPlatform *platform, NMFakePlatformLink *device, gboolean raise_signal);
|
||||
|
||||
static gboolean ip6_address_add (NMPlatform *platform, int ifindex,
|
||||
struct in6_addr addr, struct in6_addr peer_addr,
|
||||
int plen, guint32 lifetime, guint32 preferred, guint flags);
|
||||
static gboolean ip6_address_delete (NMPlatform *platform, int ifindex, struct in6_addr addr, int plen);
|
||||
|
||||
/******************************************************************/
|
||||
|
||||
static gboolean
|
||||
sysctl_set (NMPlatform *platform, const char *path, const char *value)
|
||||
{
|
||||
|
|
@ -103,24 +117,30 @@ type_to_type_name (NMLinkType type)
|
|||
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->link.udi = device->udi = g_strdup_printf ("fake:%d", ifindex);
|
||||
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.arp = FALSE;
|
||||
device->link.flags = NM_FLAGS_SET (device->link.flags, IFF_NOARP);
|
||||
break;
|
||||
default:
|
||||
device->link.arp = TRUE;
|
||||
device->link.flags = NM_FLAGS_UNSET (device->link.flags, IFF_NOARP);
|
||||
break;
|
||||
}
|
||||
device->address = NULL;
|
||||
}
|
||||
|
|
@ -140,7 +160,6 @@ link_get (NMPlatform *platform, int ifindex)
|
|||
return device;
|
||||
not_found:
|
||||
debug ("link not found: %d", ifindex);
|
||||
platform->error = NM_PLATFORM_ERROR_NOT_FOUND;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -205,9 +224,12 @@ link_add (NMPlatform *platform,
|
|||
|
||||
g_array_append_val (priv->links, device);
|
||||
|
||||
if (device.link.ifindex)
|
||||
if (device.link.ifindex) {
|
||||
g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_LINK_CHANGED, device.link.ifindex, &device, NM_PLATFORM_SIGNAL_ADDED, NM_PLATFORM_REASON_INTERNAL);
|
||||
|
||||
link_changed (platform, &g_array_index (priv->links, NMFakePlatformLink, priv->links->len - 1), FALSE);
|
||||
}
|
||||
|
||||
if (out_link)
|
||||
*out_link = device.link;
|
||||
return TRUE;
|
||||
|
|
@ -303,55 +325,76 @@ link_get_unmanaged (NMPlatform *platform, int ifindex, gboolean *managed)
|
|||
}
|
||||
|
||||
static void
|
||||
link_changed (NMPlatform *platform, NMFakePlatformLink *device)
|
||||
link_changed (NMPlatform *platform, NMFakePlatformLink *device, gboolean raise_signal)
|
||||
{
|
||||
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
|
||||
int i;
|
||||
|
||||
g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_LINK_CHANGED, device->link.ifindex, &device->link, NM_PLATFORM_SIGNAL_CHANGED, NM_PLATFORM_REASON_INTERNAL);
|
||||
if (raise_signal)
|
||||
g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_LINK_CHANGED, device->link.ifindex, &device->link, NM_PLATFORM_SIGNAL_CHANGED, NM_PLATFORM_REASON_INTERNAL);
|
||||
|
||||
if (device->link.ifindex && !IN6_IS_ADDR_UNSPECIFIED (&device->ip6_lladdr)) {
|
||||
if (device->link.connected)
|
||||
ip6_address_add (platform, device->link.ifindex, device->ip6_lladdr, in6addr_any, 64, NM_PLATFORM_LIFETIME_PERMANENT, NM_PLATFORM_LIFETIME_PERMANENT, 0);
|
||||
else
|
||||
ip6_address_delete (platform, device->link.ifindex, device->ip6_lladdr, 64);
|
||||
}
|
||||
|
||||
if (device->link.master) {
|
||||
gboolean connected = FALSE;
|
||||
|
||||
NMFakePlatformLink *master = link_get (platform, device->link.master);
|
||||
|
||||
g_return_if_fail (master != device);
|
||||
g_return_if_fail (master && master != device);
|
||||
|
||||
master->link.connected = FALSE;
|
||||
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)
|
||||
master->link.connected = TRUE;
|
||||
connected = TRUE;
|
||||
}
|
||||
|
||||
link_changed (platform, master);
|
||||
if (master->link.connected != connected) {
|
||||
master->link.connected = connected;
|
||||
link_changed (platform, master, TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
link_set_up (NMPlatform *platform, int ifindex)
|
||||
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;
|
||||
|
||||
if (!device)
|
||||
return FALSE;
|
||||
|
||||
device->link.up = TRUE;
|
||||
up = TRUE;
|
||||
connected = TRUE;
|
||||
switch (device->link.type) {
|
||||
case NM_LINK_TYPE_DUMMY:
|
||||
case NM_LINK_TYPE_VLAN:
|
||||
device->link.connected = TRUE;
|
||||
break;
|
||||
case NM_LINK_TYPE_BRIDGE:
|
||||
case NM_LINK_TYPE_BOND:
|
||||
case NM_LINK_TYPE_TEAM:
|
||||
device->link.connected = FALSE;
|
||||
connected = FALSE;
|
||||
break;
|
||||
default:
|
||||
device->link.connected = FALSE;
|
||||
connected = FALSE;
|
||||
g_error ("Unexpected device type: %d", device->link.type);
|
||||
}
|
||||
|
||||
link_changed (platform, device);
|
||||
if ( NM_FLAGS_HAS (device->link.flags, IFF_UP) != !!up
|
||||
|| device->link.connected != connected) {
|
||||
device->link.flags = NM_FLAGS_ASSIGN (device->link.flags, IFF_UP, up);
|
||||
device->link.connected = connected;
|
||||
link_changed (platform, device, TRUE);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -364,10 +407,12 @@ link_set_down (NMPlatform *platform, int ifindex)
|
|||
if (!device)
|
||||
return FALSE;
|
||||
|
||||
device->link.up = FALSE;
|
||||
device->link.connected = FALSE;
|
||||
if (NM_FLAGS_HAS (device->link.flags, IFF_UP) || device->link.connected) {
|
||||
device->link.flags = NM_FLAGS_UNSET (device->link.flags, IFF_UP);
|
||||
device->link.connected = FALSE;
|
||||
|
||||
link_changed (platform, device);
|
||||
link_changed (platform, device, TRUE);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -380,9 +425,9 @@ link_set_arp (NMPlatform *platform, int ifindex)
|
|||
if (!device)
|
||||
return FALSE;
|
||||
|
||||
device->link.arp = TRUE;
|
||||
device->link.flags = NM_FLAGS_UNSET (device->link.flags, IFF_NOARP);
|
||||
|
||||
link_changed (platform, device);
|
||||
link_changed (platform, device, TRUE);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -395,9 +440,9 @@ link_set_noarp (NMPlatform *platform, int ifindex)
|
|||
if (!device)
|
||||
return FALSE;
|
||||
|
||||
device->link.arp = FALSE;
|
||||
device->link.flags = NM_FLAGS_SET (device->link.flags, IFF_NOARP);
|
||||
|
||||
link_changed (platform, device);
|
||||
link_changed (platform, device, TRUE);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -407,7 +452,7 @@ link_is_up (NMPlatform *platform, int ifindex)
|
|||
{
|
||||
NMFakePlatformLink *device = link_get (platform, ifindex);
|
||||
|
||||
return device ? device->link.up : FALSE;
|
||||
return device ? NM_FLAGS_HAS (device->link.flags, IFF_UP) : FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
@ -423,7 +468,7 @@ link_uses_arp (NMPlatform *platform, int ifindex)
|
|||
{
|
||||
NMFakePlatformLink *device = link_get (platform, ifindex);
|
||||
|
||||
return device ? device->link.arp : FALSE;
|
||||
return device ? !NM_FLAGS_HAS (device->link.flags, IFF_NOARP) : FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
@ -436,7 +481,7 @@ link_set_address (NMPlatform *platform, int ifindex, gconstpointer addr, size_t
|
|||
|
||||
device->address = g_bytes_new (addr, len);
|
||||
|
||||
link_changed (platform, link_get (platform, ifindex));
|
||||
link_changed (platform, link_get (platform, ifindex), TRUE);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -468,7 +513,7 @@ link_set_mtu (NMPlatform *platform, int ifindex, guint32 mtu)
|
|||
|
||||
if (device) {
|
||||
device->link.mtu = mtu;
|
||||
link_changed (platform, device);
|
||||
link_changed (platform, device, TRUE);
|
||||
}
|
||||
|
||||
return !!device;
|
||||
|
|
@ -500,6 +545,16 @@ link_get_dev_id (NMPlatform *platform, int ifindex)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static const char *
|
||||
link_get_udi (NMPlatform *platform, int ifindex)
|
||||
{
|
||||
NMFakePlatformLink *device = link_get (platform, ifindex);
|
||||
|
||||
if (!device)
|
||||
return NULL;
|
||||
return device->udi;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
link_get_wake_on_lan (NMPlatform *platform, int ifindex)
|
||||
{
|
||||
|
|
@ -565,12 +620,21 @@ static gboolean
|
|||
link_enslave (NMPlatform *platform, int master, int slave)
|
||||
{
|
||||
NMFakePlatformLink *device = link_get (platform, slave);
|
||||
NMFakePlatformLink *master_device = link_get (platform, master);
|
||||
|
||||
g_return_val_if_fail (device, FALSE);
|
||||
g_return_val_if_fail (master_device, FALSE);
|
||||
|
||||
device->link.master = master;
|
||||
if (device->link.master != master) {
|
||||
device->link.master = master;
|
||||
|
||||
link_changed (platform, device);
|
||||
if (NM_IN_SET (master_device->link.type, NM_LINK_TYPE_BOND, NM_LINK_TYPE_TEAM)) {
|
||||
device->link.flags = NM_FLAGS_SET (device->link.flags, IFF_UP);
|
||||
device->link.connected = TRUE;
|
||||
}
|
||||
|
||||
link_changed (platform, device, TRUE);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -584,15 +648,13 @@ link_release (NMPlatform *platform, int master_idx, int slave_idx)
|
|||
g_return_val_if_fail (master, FALSE);
|
||||
g_return_val_if_fail (slave, FALSE);
|
||||
|
||||
if (slave->link.master != master->link.ifindex) {
|
||||
platform->error = NM_PLATFORM_ERROR_NOT_SLAVE;
|
||||
if (slave->link.master != master->link.ifindex)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
slave->link.master = 0;
|
||||
|
||||
link_changed (platform, slave);
|
||||
link_changed (platform, master);
|
||||
link_changed (platform, slave, TRUE);
|
||||
link_changed (platform, master, TRUE);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -982,8 +1044,10 @@ ip6_address_add (NMPlatform *platform, int ifindex,
|
|||
if (item->plen != address.plen)
|
||||
continue;
|
||||
|
||||
memcpy (item, &address, sizeof (address));
|
||||
g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED, ifindex, &address, NM_PLATFORM_SIGNAL_CHANGED, NM_PLATFORM_REASON_INTERNAL);
|
||||
if (nm_platform_ip6_address_cmp (item, &address) != 0) {
|
||||
memcpy (item, &address, sizeof (address));
|
||||
g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED, ifindex, &address, NM_PLATFORM_SIGNAL_CHANGED, NM_PLATFORM_REASON_INTERNAL);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -1196,6 +1260,9 @@ ip4_route_add (NMPlatform *platform, int ifindex, NMIPConfigSource source,
|
|||
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
|
||||
NMPlatformIP4Route route;
|
||||
guint i;
|
||||
guint8 scope;
|
||||
|
||||
scope = gateway == 0 ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSE;
|
||||
|
||||
memset (&route, 0, sizeof (route));
|
||||
route.source = NM_IP_CONFIG_SOURCE_KERNEL;
|
||||
|
|
@ -1206,6 +1273,7 @@ ip4_route_add (NMPlatform *platform, int ifindex, NMIPConfigSource source,
|
|||
route.gateway = gateway;
|
||||
route.metric = metric;
|
||||
route.mss = mss;
|
||||
route.scope_inv = nm_platform_route_scope_inv (scope);
|
||||
|
||||
if (gateway) {
|
||||
for (i = 0; i < priv->ip4_routes->len; i++) {
|
||||
|
|
@ -1218,8 +1286,8 @@ ip4_route_add (NMPlatform *platform, int ifindex, NMIPConfigSource source,
|
|||
break;
|
||||
}
|
||||
if (i == priv->ip4_routes->len) {
|
||||
nm_log_warn (LOGD_PLATFORM, "Fake platform: error adding %s: Network Unreachable",
|
||||
nm_platform_ip4_route_to_string (&route));
|
||||
nm_log_warn (LOGD_PLATFORM, "Fake platform: failure adding ip4-route '%d: %s/%d %d': Network Unreachable",
|
||||
route.ifindex, nm_utils_inet4_ntop (route.network, NULL), route.plen, route.metric);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
|
@ -1285,8 +1353,8 @@ ip6_route_add (NMPlatform *platform, int ifindex, NMIPConfigSource source,
|
|||
break;
|
||||
}
|
||||
if (i == priv->ip6_routes->len) {
|
||||
nm_log_warn (LOGD_PLATFORM, "Fake platform: error adding %s: Network Unreachable",
|
||||
nm_platform_ip6_route_to_string (&route));
|
||||
nm_log_warn (LOGD_PLATFORM, "Fake platform: failure adding ip6-route '%d: %s/%d %d': Network Unreachable",
|
||||
route.ifindex, nm_utils_inet6_ntop (&route.network, NULL), route.plen, route.metric);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
|
@ -1453,6 +1521,8 @@ nm_fake_platform_class_init (NMFakePlatformClass *klass)
|
|||
platform_class->link_get_type_name = link_get_type_name;
|
||||
platform_class->link_get_unmanaged = link_get_unmanaged;
|
||||
|
||||
platform_class->link_get_udi = link_get_udi;
|
||||
|
||||
platform_class->link_set_up = link_set_up;
|
||||
platform_class->link_set_down = link_set_down;
|
||||
platform_class->link_set_arp = link_set_arp;
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -32,8 +32,12 @@
|
|||
|
||||
/******************************************************************/
|
||||
|
||||
struct _NMLinuxPlatformPrivate;
|
||||
|
||||
typedef struct {
|
||||
NMPlatform parent;
|
||||
|
||||
struct _NMLinuxPlatformPrivate *priv;
|
||||
} NMLinuxPlatform;
|
||||
|
||||
typedef struct {
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
#include <nm-dbus-interface.h>
|
||||
#include "nm-types.h"
|
||||
#include "NetworkManagerUtils.h"
|
||||
|
||||
#define NM_TYPE_PLATFORM (nm_platform_get_type ())
|
||||
#define NM_PLATFORM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_PLATFORM, NMPlatform))
|
||||
|
|
@ -39,6 +40,10 @@
|
|||
|
||||
/******************************************************************/
|
||||
|
||||
#define NM_PLATFORM_REGISTER_SINGLETON "register-singleton"
|
||||
|
||||
/******************************************************************/
|
||||
|
||||
typedef struct _NMPlatform NMPlatform;
|
||||
|
||||
/* workaround for older libnl version, that does not define these flags. */
|
||||
|
|
@ -50,18 +55,23 @@ typedef struct _NMPlatform NMPlatform;
|
|||
#endif
|
||||
|
||||
typedef enum {
|
||||
/* no error specified, sometimes this means the arguments were wrong */
|
||||
NM_PLATFORM_ERROR_NONE,
|
||||
/* object was not found */
|
||||
|
||||
/* dummy value, to enforce that the enum type is signed and has a size
|
||||
* to hold an integer. We want to encode errno from <errno.h> as negative
|
||||
* values. */
|
||||
_NM_PLATFORM_ERROR_MININT = G_MININT,
|
||||
|
||||
NM_PLATFORM_ERROR_SUCCESS = 0,
|
||||
|
||||
NM_PLATFORM_ERROR_BUG,
|
||||
|
||||
NM_PLATFORM_ERROR_UNSPECIFIED,
|
||||
|
||||
NM_PLATFORM_ERROR_NOT_FOUND,
|
||||
/* object already exists */
|
||||
NM_PLATFORM_ERROR_EXISTS,
|
||||
/* object is wrong type */
|
||||
NM_PLATFORM_ERROR_WRONG_TYPE,
|
||||
/* object is not a slave */
|
||||
NM_PLATFORM_ERROR_NOT_SLAVE,
|
||||
/* firmware is not found */
|
||||
NM_PLATFORM_ERROR_NO_FIRMWARE
|
||||
NM_PLATFORM_ERROR_NO_FIRMWARE,
|
||||
} NMPlatformError;
|
||||
|
||||
typedef enum {
|
||||
|
|
@ -90,19 +100,44 @@ struct _NMPlatformLink {
|
|||
/* NMPlatform initializes this field with a static string. */
|
||||
const char *kind;
|
||||
|
||||
/* Beware: NMPlatform initializes this string with an allocated string.
|
||||
* Handle it properly (i.e. don't keep a reference to it). */
|
||||
const char *udi;
|
||||
|
||||
/* NMPlatform initializes this field with a static string. */
|
||||
const char *driver;
|
||||
|
||||
gboolean initialized;
|
||||
int master;
|
||||
int parent;
|
||||
gboolean up;
|
||||
|
||||
/* rtnl_link_get_arptype(), ifinfomsg.ifi_type. */
|
||||
guint32 arptype;
|
||||
|
||||
/* rtnl_link_get_addr() */
|
||||
struct {
|
||||
guint8 data[20]; /* NM_UTILS_HWADDR_LEN_MAX */
|
||||
guint8 len;
|
||||
} addr;
|
||||
|
||||
/* rtnl_link_inet6_get_token() */
|
||||
struct {
|
||||
NMUtilsIPv6IfaceId iid;
|
||||
guint8 is_valid;
|
||||
} inet6_token;
|
||||
|
||||
/* The bitwise inverse of rtnl_link_inet6_get_addr_gen_mode(). It is inverse
|
||||
* to have a default of 0 -- meaning: unspecified. That way, a struct
|
||||
* initialized with memset(0) has and unset value.*/
|
||||
guint8 inet6_addr_gen_mode_inv;
|
||||
|
||||
/* rtnl_link_vlan_get_id(), IFLA_VLAN_ID */
|
||||
guint16 vlan_id;
|
||||
|
||||
/* IFF_* flags as u32. Note that ifi_flags in 'struct ifinfomsg' is declared as 'unsigned',
|
||||
* but libnl stores the flag internally as u32. */
|
||||
guint32 flags;
|
||||
|
||||
/* @connected is mostly identical to (@flags & IFF_UP). Except for bridge/bond masters,
|
||||
* where we coerce the link as disconnect if it has no slaves. */
|
||||
gboolean connected;
|
||||
gboolean arp;
|
||||
|
||||
guint mtu;
|
||||
};
|
||||
|
||||
|
|
@ -237,6 +272,10 @@ struct _NMPlatformIP4Route {
|
|||
__NMPlatformIPRoute_COMMON;
|
||||
in_addr_t network;
|
||||
in_addr_t gateway;
|
||||
|
||||
/* The bitwise inverse of the route scope. It is inverted so that the
|
||||
* default value (RT_SCOPE_NOWHERE) is nul. */
|
||||
guint8 scope_inv;
|
||||
};
|
||||
G_STATIC_ASSERT (G_STRUCT_OFFSET (NMPlatformIPRoute, network_ptr) == G_STRUCT_OFFSET (NMPlatformIP4Route, network));
|
||||
|
||||
|
|
@ -275,6 +314,7 @@ typedef struct {
|
|||
extern const NMPlatformVTableRoute nm_platform_vtable_route_v4;
|
||||
extern const NMPlatformVTableRoute nm_platform_vtable_route_v6;
|
||||
|
||||
extern char _nm_platform_to_string_buffer[256];
|
||||
|
||||
typedef struct {
|
||||
int peer;
|
||||
|
|
@ -361,8 +401,6 @@ typedef struct {
|
|||
|
||||
struct _NMPlatform {
|
||||
GObject parent;
|
||||
|
||||
NMPlatformError error;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
|
|
@ -389,7 +427,7 @@ typedef struct {
|
|||
|
||||
gboolean (*link_refresh) (NMPlatform *, int ifindex);
|
||||
|
||||
gboolean (*link_set_up) (NMPlatform *, int ifindex);
|
||||
gboolean (*link_set_up) (NMPlatform *, int ifindex, gboolean *out_no_firmware);
|
||||
gboolean (*link_set_down) (NMPlatform *, int ifindex);
|
||||
gboolean (*link_set_arp) (NMPlatform *, int ifindex);
|
||||
gboolean (*link_set_noarp) (NMPlatform *, int ifindex);
|
||||
|
|
@ -397,6 +435,8 @@ typedef struct {
|
|||
gboolean (*link_is_connected) (NMPlatform *, int ifindex);
|
||||
gboolean (*link_uses_arp) (NMPlatform *, int ifindex);
|
||||
|
||||
const char *(*link_get_udi) (NMPlatform *self, int ifindex);
|
||||
GObject *(*link_get_udev_device) (NMPlatform *self, int ifindex);
|
||||
gboolean (*link_get_ipv6_token) (NMPlatform *, int ifindex, NMUtilsIPv6IfaceId *iid);
|
||||
|
||||
gboolean (*link_get_user_ipv6ll_enabled) (NMPlatform *, int ifindex);
|
||||
|
|
@ -529,11 +569,25 @@ NMPlatform *nm_platform_try_get (void);
|
|||
|
||||
/******************************************************************/
|
||||
|
||||
/**
|
||||
* nm_platform_route_scope_inv:
|
||||
* @scope: the route scope, either its original value, or its inverse.
|
||||
*
|
||||
* This function is useful, because the constants such as RT_SCOPE_NOWHERE
|
||||
* are 'int', so ~scope also gives an 'int'. This function gets the type
|
||||
* casts to guint8 right.
|
||||
*
|
||||
* Returns: the bitwise inverse of the route scope.
|
||||
* */
|
||||
static inline guint8
|
||||
nm_platform_route_scope_inv (guint8 scope)
|
||||
{
|
||||
return (guint8) ~scope;
|
||||
}
|
||||
|
||||
const char *nm_link_type_to_string (NMLinkType link_type);
|
||||
|
||||
void nm_platform_set_error (NMPlatform *self, NMPlatformError error);
|
||||
NMPlatformError nm_platform_get_error (NMPlatform *self);
|
||||
const char *nm_platform_get_error_msg (NMPlatform *self);
|
||||
const char *nm_platform_error_to_string (NMPlatformError error);
|
||||
|
||||
gboolean nm_platform_sysctl_set (NMPlatform *self, const char *path, const char *value);
|
||||
char *nm_platform_sysctl_get (NMPlatform *self, const char *path);
|
||||
|
|
@ -545,10 +599,10 @@ gboolean nm_platform_sysctl_set_ip6_hop_limit_safe (NMPlatform *self, const char
|
|||
gboolean nm_platform_link_get (NMPlatform *self, int ifindex, NMPlatformLink *link);
|
||||
GArray *nm_platform_link_get_all (NMPlatform *self);
|
||||
gboolean nm_platform_link_get_by_address (NMPlatform *self, gconstpointer address, size_t length, NMPlatformLink *link);
|
||||
gboolean nm_platform_dummy_add (NMPlatform *self, const char *name, NMPlatformLink *out_link);
|
||||
gboolean nm_platform_bridge_add (NMPlatform *self, const char *name, const void *address, size_t address_len, NMPlatformLink *out_link);
|
||||
gboolean nm_platform_bond_add (NMPlatform *self, const char *name, NMPlatformLink *out_link);
|
||||
gboolean nm_platform_team_add (NMPlatform *self, const char *name, NMPlatformLink *out_link);
|
||||
NMPlatformError nm_platform_dummy_add (NMPlatform *self, const char *name, NMPlatformLink *out_link);
|
||||
NMPlatformError nm_platform_bridge_add (NMPlatform *self, const char *name, const void *address, size_t address_len, NMPlatformLink *out_link);
|
||||
NMPlatformError nm_platform_bond_add (NMPlatform *self, const char *name, NMPlatformLink *out_link);
|
||||
NMPlatformError nm_platform_team_add (NMPlatform *self, const char *name, NMPlatformLink *out_link);
|
||||
gboolean nm_platform_link_exists (NMPlatform *self, const char *name);
|
||||
gboolean nm_platform_link_delete (NMPlatform *self, int ifindex);
|
||||
int nm_platform_link_get_ifindex (NMPlatform *self, const char *name);
|
||||
|
|
@ -561,7 +615,7 @@ gboolean nm_platform_link_supports_slaves (NMPlatform *self, int ifindex);
|
|||
|
||||
gboolean nm_platform_link_refresh (NMPlatform *self, int ifindex);
|
||||
|
||||
gboolean nm_platform_link_set_up (NMPlatform *self, int ifindex);
|
||||
gboolean nm_platform_link_set_up (NMPlatform *self, int ifindex, gboolean *out_no_firmware);
|
||||
gboolean nm_platform_link_set_down (NMPlatform *self, int ifindex);
|
||||
gboolean nm_platform_link_set_arp (NMPlatform *self, int ifindex);
|
||||
gboolean nm_platform_link_set_noarp (NMPlatform *self, int ifindex);
|
||||
|
|
@ -570,6 +624,9 @@ gboolean nm_platform_link_is_connected (NMPlatform *self, int ifindex);
|
|||
gboolean nm_platform_link_uses_arp (NMPlatform *self, int ifindex);
|
||||
|
||||
gboolean nm_platform_link_get_ipv6_token (NMPlatform *self, int ifindex, NMUtilsIPv6IfaceId *iid);
|
||||
const char *nm_platform_link_get_udi (NMPlatform *self, int ifindex);
|
||||
|
||||
GObject *nm_platform_link_get_udev_device (NMPlatform *self, int ifindex);
|
||||
|
||||
gboolean nm_platform_link_get_user_ipv6ll_enabled (NMPlatform *self, int ifindex);
|
||||
gboolean nm_platform_link_set_user_ipv6ll_enabled (NMPlatform *self, int ifindex, gboolean enabled);
|
||||
|
|
@ -600,12 +657,12 @@ 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);
|
||||
|
||||
gboolean nm_platform_vlan_add (NMPlatform *self, const char *name, int parent, int vlanid, guint32 vlanflags, NMPlatformLink *out_link);
|
||||
NMPlatformError nm_platform_vlan_add (NMPlatform *self, const char *name, int parent, int vlanid, guint32 vlanflags, NMPlatformLink *out_link);
|
||||
gboolean nm_platform_vlan_get_info (NMPlatform *self, int ifindex, int *parent, int *vlanid);
|
||||
gboolean nm_platform_vlan_set_ingress_map (NMPlatform *self, int ifindex, int from, int to);
|
||||
gboolean nm_platform_vlan_set_egress_map (NMPlatform *self, int ifindex, int from, int to);
|
||||
|
||||
gboolean nm_platform_infiniband_partition_add (NMPlatform *self, int parent, int p_key, NMPlatformLink *out_link);
|
||||
NMPlatformError nm_platform_infiniband_partition_add (NMPlatform *self, int parent, int p_key, NMPlatformLink *out_link);
|
||||
gboolean nm_platform_infiniband_get_info (NMPlatform *self, int ifindex, int *parent, int *p_key, const char **mode);
|
||||
|
||||
gboolean nm_platform_veth_get_properties (NMPlatform *self, int ifindex, NMPlatformVethProperties *properties);
|
||||
|
|
|
|||
1941
src/platform/nmp-object.c
Normal file
1941
src/platform/nmp-object.c
Normal file
File diff suppressed because it is too large
Load diff
383
src/platform/nmp-object.h
Normal file
383
src/platform/nmp-object.h
Normal file
|
|
@ -0,0 +1,383 @@
|
|||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
||||
/* nm-platform.c - Handle runtime kernel networking configuration
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Copyright (C) 2015 Red Hat, Inc.
|
||||
*/
|
||||
|
||||
#ifndef __NMP_OBJECT_H__
|
||||
#define __NMP_OBJECT_H__
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "nm-platform.h"
|
||||
#include "nm-multi-index.h"
|
||||
#include "nm-macros-internal.h"
|
||||
|
||||
#include <netlink/netlink.h>
|
||||
#include <gudev/gudev.h>
|
||||
|
||||
|
||||
typedef enum { /*< skip >*/
|
||||
OBJECT_TYPE_UNKNOWN,
|
||||
OBJECT_TYPE_LINK,
|
||||
OBJECT_TYPE_IP4_ADDRESS,
|
||||
OBJECT_TYPE_IP6_ADDRESS,
|
||||
OBJECT_TYPE_IP4_ROUTE,
|
||||
OBJECT_TYPE_IP6_ROUTE,
|
||||
__OBJECT_TYPE_LAST,
|
||||
OBJECT_TYPE_MAX = __OBJECT_TYPE_LAST - 1,
|
||||
} ObjectType;
|
||||
|
||||
typedef enum { /*< skip >*/
|
||||
NMP_OBJECT_TO_STRING_ID,
|
||||
NMP_OBJECT_TO_STRING_PUBLIC,
|
||||
NMP_OBJECT_TO_STRING_ALL,
|
||||
} NMPObjectToStringMode;
|
||||
|
||||
typedef enum { /*< skip >*/
|
||||
NMP_CACHE_OPS_UNCHANGED = NM_PLATFORM_SIGNAL_NONE,
|
||||
NMP_CACHE_OPS_UPDATED = NM_PLATFORM_SIGNAL_CHANGED,
|
||||
NMP_CACHE_OPS_ADDED = NM_PLATFORM_SIGNAL_ADDED,
|
||||
NMP_CACHE_OPS_REMOVED = NM_PLATFORM_SIGNAL_REMOVED,
|
||||
} NMPCacheOpsType;
|
||||
|
||||
/* The NMPCacheIdType are the different index types.
|
||||
*
|
||||
* An object of a certain object-type, can be candidate to being
|
||||
* indexed by a certain NMPCacheIdType or not. For example, all
|
||||
* objects are indexed via an index of type NMP_CACHE_ID_TYPE_OBJECT_TYPE,
|
||||
* but only route objects are indexed by NMP_CACHE_ID_TYPE_ROUTES_VISIBLE_ALL.
|
||||
*
|
||||
* Of one index type, there can be different indexes or not.
|
||||
* For example, there is only one single instance of
|
||||
* NMP_CACHE_ID_TYPE_LINKS_VISIBLE_ONLY, because this instance is
|
||||
* applicable for all link objects.
|
||||
* But there are different instances of NMP_CACHE_ID_TYPE_ADDRROUTE_BY_IFINDEX
|
||||
* type index, which differ in v4/v6, the ifindex, and whether the index
|
||||
* is for routes or address instances.
|
||||
*
|
||||
* But one object, can only be indexed by one particular index of one
|
||||
* type. For example, a certain address instance is only indexed by
|
||||
* the index NMP_CACHE_ID_TYPE_ADDRROUTE_BY_IFINDEX with matching v4/v6
|
||||
* and ifindex.
|
||||
* */
|
||||
typedef enum { /*< skip >*/
|
||||
NMP_CACHE_ID_TYPE_OBJECT_TYPE,
|
||||
|
||||
NMP_CACHE_ID_TYPE_LINKS_VISIBLE_ONLY,
|
||||
|
||||
NMP_CACHE_ID_TYPE_ADDRROUTE_BY_IFINDEX,
|
||||
|
||||
/* three indeces for the visibile routes. */
|
||||
NMP_CACHE_ID_TYPE_ROUTES_VISIBLE_ALL,
|
||||
NMP_CACHE_ID_TYPE_ROUTES_VISIBLE_NO_DEFAULT,
|
||||
NMP_CACHE_ID_TYPE_ROUTES_VISIBLE_ONLY_DEFAULT,
|
||||
|
||||
__NMP_CACHE_ID_TYPE_MAX,
|
||||
NMP_CACHE_ID_TYPE_MAX = __NMP_CACHE_ID_TYPE_MAX - 1,
|
||||
} NMPCacheIdType;
|
||||
|
||||
typedef struct _NMPObject NMPObject;
|
||||
|
||||
typedef struct {
|
||||
union {
|
||||
NMMultiIndexId base;
|
||||
guint8 _id_type; /* NMPCacheIdType as guint8 */
|
||||
struct {
|
||||
/* NMP_CACHE_ID_TYPE_OBJECT_TYPE */
|
||||
guint8 _id_type;
|
||||
guint8 obj_type; /* ObjectType as guint8 */
|
||||
} object_type;
|
||||
struct {
|
||||
/* NMP_CACHE_ID_TYPE_LINKS_VISIBLE_ONLY */
|
||||
guint8 _id_type;
|
||||
|
||||
/* the @_global_id is only defined by it's type and has no arguments.
|
||||
* It is used by NMP_CACHE_ID_TYPE_LINKS_VISIBLE_ONLY. There is only
|
||||
* one single occurence of an index of this type. */
|
||||
} _global_id;
|
||||
struct {
|
||||
/* NMP_CACHE_ID_TYPE_ADDRROUTE_BY_IFINDEX */
|
||||
guint8 _id_type;
|
||||
guint8 obj_type; /* ObjectType as guint8 */
|
||||
int ifindex;
|
||||
} addrroute_by_ifindex;
|
||||
struct {
|
||||
/* NMP_CACHE_ID_TYPE_ROUTES_VISIBLE_ALL */
|
||||
/* NMP_CACHE_ID_TYPE_ROUTES_VISIBLE_NO_DEFAULT */
|
||||
/* NMP_CACHE_ID_TYPE_ROUTES_VISIBLE_ONLY_DEFAULT */
|
||||
guint8 _id_type;
|
||||
guint8 is_v4;
|
||||
int ifindex;
|
||||
} routes_visible;
|
||||
};
|
||||
} NMPCacheId;
|
||||
|
||||
extern NMPCacheId _nmp_cache_id_static;
|
||||
#define NMP_CACHE_ID_STATIC (&_nmp_cache_id_static)
|
||||
|
||||
typedef struct {
|
||||
ObjectType obj_type;
|
||||
int addr_family;
|
||||
int rtm_gettype;
|
||||
int sizeof_data;
|
||||
int sizeof_public;
|
||||
const char *obj_type_name;
|
||||
const char *nl_type;
|
||||
const char *signal_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);
|
||||
|
||||
gboolean (*cmd_obj_equal) (const NMPObject *obj1, const NMPObject *obj2);
|
||||
void (*cmd_obj_copy) (NMPObject *dst, const NMPObject *src);
|
||||
void (*cmd_obj_stackinit_id) (NMPObject *obj, const NMPObject *src);
|
||||
void (*cmd_obj_dispose) (NMPObject *obj);
|
||||
gboolean (*cmd_obj_is_alive) (const NMPObject *obj);
|
||||
gboolean (*cmd_obj_is_visible) (const NMPObject *obj);
|
||||
|
||||
/* functions that operate on NMPlatformObject */
|
||||
gboolean (*cmd_plobj_init_from_nl) (NMPlatform *platform, NMPlatformObject *obj, const struct nl_object *nlo, gboolean id_only, gboolean complete_from_cache);
|
||||
struct nl_object *(*cmd_plobj_to_nl) (NMPlatform *platform, const NMPlatformObject *obj, gboolean id_only);
|
||||
void (*cmd_plobj_id_copy) (NMPlatformObject *dst, const NMPlatformObject *src);
|
||||
gboolean (*cmd_plobj_id_equal) (const NMPlatformObject *obj1, const NMPlatformObject *obj2);
|
||||
guint (*cmd_plobj_id_hash) (const NMPlatformObject *obj);
|
||||
const char *(*cmd_plobj_to_string_id) (const NMPlatformObject *obj, char *buf, gsize buf_size);
|
||||
const char *(*cmd_plobj_to_string) (const NMPlatformObject *obj);
|
||||
int (*cmd_plobj_cmp) (const NMPlatformObject *obj1, const NMPlatformObject *obj2);
|
||||
} NMPClass;
|
||||
|
||||
extern const NMPClass _nmp_classes[OBJECT_TYPE_MAX];
|
||||
|
||||
typedef struct {
|
||||
NMPlatformLink _public;
|
||||
|
||||
struct {
|
||||
guint8 is_in_netlink;
|
||||
} netlink;
|
||||
|
||||
struct {
|
||||
GUdevDevice *device;
|
||||
} udev;
|
||||
} NMPObjectLink;
|
||||
|
||||
typedef struct {
|
||||
NMPlatformIP4Address _public;
|
||||
} NMPObjectIP4Address;
|
||||
|
||||
typedef struct {
|
||||
NMPlatformIP4Route _public;
|
||||
} NMPObjectIP4Route;
|
||||
|
||||
typedef struct {
|
||||
NMPlatformIP6Address _public;
|
||||
} NMPObjectIP6Address;
|
||||
|
||||
typedef struct {
|
||||
NMPlatformIP6Route _public;
|
||||
} NMPObjectIP6Route;
|
||||
|
||||
struct _NMPObject {
|
||||
const NMPClass *_class;
|
||||
int _ref_count;
|
||||
guint8 is_cached;
|
||||
union {
|
||||
NMPlatformObject object;
|
||||
|
||||
NMPlatformLink link;
|
||||
NMPObjectLink _link;
|
||||
|
||||
NMPlatformIPAddress ip_address;
|
||||
NMPlatformIPXAddress ipx_address;
|
||||
NMPlatformIP4Address ip4_address;
|
||||
NMPlatformIP6Address ip6_address;
|
||||
NMPObjectIP4Address _ip4_address;
|
||||
NMPObjectIP6Address _ip6_address;
|
||||
|
||||
NMPlatformIPRoute ip_route;
|
||||
NMPlatformIPXRoute ipx_route;
|
||||
NMPlatformIP4Route ip4_route;
|
||||
NMPlatformIP6Route ip6_route;
|
||||
NMPObjectIP4Route _ip4_route;
|
||||
NMPObjectIP6Route _ip6_route;
|
||||
};
|
||||
};
|
||||
|
||||
static inline gboolean
|
||||
NMP_CLASS_IS_VALID (const NMPClass *klass)
|
||||
{
|
||||
return klass >= &_nmp_classes[0]
|
||||
&& klass <= &_nmp_classes[G_N_ELEMENTS (_nmp_classes)]
|
||||
&& ((((char *) klass) - ((char *) NULL)) % (&_nmp_classes[1] - &_nmp_classes[0])) == 0;
|
||||
}
|
||||
|
||||
#define NMP_REF_COUNT_STACKINIT (G_MAXINT)
|
||||
|
||||
static inline NMPObject *
|
||||
NMP_OBJECT_UP_CAST(const NMPlatformObject *plobj)
|
||||
{
|
||||
NMPObject *obj;
|
||||
|
||||
obj = plobj
|
||||
? (NMPObject *) ( &(((char *) plobj)[-((int) G_STRUCT_OFFSET (NMPObject, object))]) )
|
||||
: NULL;
|
||||
nm_assert (!obj || (obj->_ref_count > 0 && NMP_CLASS_IS_VALID (obj->_class)));
|
||||
return obj;
|
||||
}
|
||||
#define NMP_OBJECT_UP_CAST(plobj) (NMP_OBJECT_UP_CAST ((const NMPlatformObject *) (plobj)))
|
||||
|
||||
static inline gboolean
|
||||
NMP_OBJECT_IS_VALID (const NMPObject *obj)
|
||||
{
|
||||
nm_assert (!obj || ( obj
|
||||
&& obj->_ref_count > 0
|
||||
&& NMP_CLASS_IS_VALID (obj->_class)));
|
||||
|
||||
/* There isn't really much to check. Either @obj is NULL, or we must
|
||||
* assume that it points to valid memory. */
|
||||
return obj != NULL;
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
NMP_OBJECT_IS_STACKINIT (const NMPObject *obj)
|
||||
{
|
||||
nm_assert (!obj || NMP_OBJECT_IS_VALID (obj));
|
||||
|
||||
return obj && obj->_ref_count == NMP_REF_COUNT_STACKINIT;
|
||||
}
|
||||
|
||||
static inline const NMPClass *
|
||||
NMP_OBJECT_GET_CLASS (const NMPObject *obj)
|
||||
{
|
||||
nm_assert (NMP_OBJECT_IS_VALID (obj));
|
||||
|
||||
return obj->_class;
|
||||
}
|
||||
|
||||
static inline ObjectType
|
||||
NMP_OBJECT_GET_TYPE (const NMPObject *obj)
|
||||
{
|
||||
nm_assert (!obj || NMP_OBJECT_IS_VALID (obj));
|
||||
|
||||
return obj ? obj->_class->obj_type : OBJECT_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const NMPClass *nmp_class_from_type (ObjectType obj_type);
|
||||
|
||||
NMPObject *nmp_object_ref (NMPObject *object);
|
||||
void nmp_object_unref (NMPObject *object);
|
||||
NMPObject *nmp_object_new (ObjectType obj_type, const NMPlatformObject *plob);
|
||||
NMPObject *nmp_object_new_link (int ifindex);
|
||||
|
||||
const NMPObject *nmp_object_stackinit (NMPObject *obj, ObjectType obj_type, const NMPlatformObject *plobj);
|
||||
const NMPObject *nmp_object_stackinit_id (NMPObject *obj, const NMPObject *src);
|
||||
const NMPObject *nmp_object_stackinit_id_link (NMPObject *obj, int ifindex);
|
||||
const NMPObject *nmp_object_stackinit_id_ip4_address (NMPObject *obj, int ifindex, guint32 address, int plen);
|
||||
const NMPObject *nmp_object_stackinit_id_ip6_address (NMPObject *obj, int ifindex, const struct in6_addr *address, int plen);
|
||||
const NMPObject *nmp_object_stackinit_id_ip4_route (NMPObject *obj, int ifindex, guint32 network, int plen, guint32 metric);
|
||||
const NMPObject *nmp_object_stackinit_id_ip6_route (NMPObject *obj, int ifindex, const struct in6_addr *network, int plen, guint32 metric);
|
||||
|
||||
const char *nmp_object_to_string (const NMPObject *obj, NMPObjectToStringMode to_string_mode, char *buf, gsize buf_size);
|
||||
int nmp_object_cmp (const NMPObject *obj1, const NMPObject *obj2);
|
||||
gboolean nmp_object_equal (const NMPObject *obj1, const NMPObject *obj2);
|
||||
void nmp_object_copy (NMPObject *dst, const NMPObject *src, gboolean id_only);
|
||||
NMPObject *nmp_object_clone (const NMPObject *obj, gboolean id_only);
|
||||
gboolean nmp_object_id_equal (const NMPObject *obj1, const NMPObject *obj2);
|
||||
guint nmp_object_id_hash (const NMPObject *obj);
|
||||
gboolean nmp_object_is_alive (const NMPObject *obj);
|
||||
gboolean nmp_object_is_visible (const NMPObject *obj);
|
||||
|
||||
void _nmp_object_fixup_link_udev_fields (NMPObject *obj, gboolean use_udev);
|
||||
|
||||
#define auto_nmp_obj __attribute__((cleanup(_nmp_auto_obj_cleanup)))
|
||||
static inline void
|
||||
_nmp_auto_obj_cleanup (NMPObject **pobj)
|
||||
{
|
||||
nmp_object_unref (*pobj);
|
||||
}
|
||||
|
||||
typedef struct _NMPCache NMPCache;
|
||||
|
||||
typedef void (*NMPCachePreHook) (NMPCache *cache, const NMPObject *old, const NMPObject *new, NMPCacheOpsType ops_type, gpointer user_data);
|
||||
typedef gboolean (*NMPObjectMatchFn) (const NMPObject *obj, gpointer user_data);
|
||||
|
||||
gboolean nmp_cache_id_equal (const NMPCacheId *a, const NMPCacheId *b);
|
||||
guint nmp_cache_id_hash (const NMPCacheId *id);
|
||||
NMPCacheId *nmp_cache_id_clone (const NMPCacheId *id);
|
||||
void nmp_cache_id_destroy (NMPCacheId *id);
|
||||
|
||||
NMPCacheId *nmp_cache_id_init (NMPCacheId *id, NMPCacheIdType id_type);
|
||||
NMPCacheId *nmp_cache_id_init_object_type (NMPCacheId *id, ObjectType obj_type);
|
||||
NMPCacheId *nmp_cache_id_init_links (NMPCacheId *id, gboolean visible_only);
|
||||
NMPCacheId *nmp_cache_id_init_addrroute_by_ifindex (NMPCacheId *id, ObjectType obj_type, int ifindex);
|
||||
NMPCacheId *nmp_cache_id_init_routes_visible (NMPCacheId *id, NMPCacheIdType id_type, gboolean is_v4, int ifindex);
|
||||
|
||||
const NMPlatformObject *const *nmp_cache_lookup_multi (const NMPCache *cache, const NMPCacheId *cache_id, guint *out_len);
|
||||
GArray *nmp_cache_lookup_multi_to_array (const NMPCache *cache, ObjectType obj_type, const NMPCacheId *cache_id);
|
||||
const NMPObject *nmp_cache_lookup_obj (const NMPCache *cache, const NMPObject *obj);
|
||||
const NMPObject *nmp_cache_lookup_link (const NMPCache *cache, int ifindex);
|
||||
|
||||
const NMPObject *nmp_cache_lookup_link_full (const NMPCache *cache,
|
||||
int ifindex,
|
||||
const char *ifname,
|
||||
gboolean visible_only,
|
||||
NMLinkType link_type,
|
||||
NMPObjectMatchFn match_fn,
|
||||
gpointer user_data);
|
||||
GHashTable *nmp_cache_lookup_all_to_hash (const NMPCache *cache,
|
||||
NMPCacheId *cache_id,
|
||||
GHashTable *hash);
|
||||
|
||||
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);
|
||||
|
||||
gboolean nmp_cache_use_udev_detect (void);
|
||||
gboolean nmp_cache_use_udev_get (const NMPCache *cache);
|
||||
gboolean nmp_cache_use_udev_set (NMPCache *cache, gboolean use_udev);
|
||||
|
||||
void ASSERT_nmp_cache_is_consistent (const NMPCache *cache);
|
||||
|
||||
NMPCacheOpsType nmp_cache_remove (NMPCache *cache, const NMPObject *obj, gboolean equals_by_ptr, NMPObject **out_obj, gboolean *out_was_visible, NMPCachePreHook pre_hook, gpointer user_data);
|
||||
NMPCacheOpsType nmp_cache_remove_netlink (NMPCache *cache, const NMPObject *obj, NMPObject **out_obj, gboolean *out_was_visible, NMPCachePreHook pre_hook, gpointer user_data);
|
||||
NMPCacheOpsType nmp_cache_update_netlink (NMPCache *cache, NMPObject *obj, NMPObject **out_obj, gboolean *out_was_visible, NMPCachePreHook pre_hook, gpointer user_data);
|
||||
NMPCacheOpsType nmp_cache_update_link_udev (NMPCache *cache, int ifindex, GUdevDevice *udev_device, NMPObject **out_obj, gboolean *out_was_visible, NMPCachePreHook pre_hook, gpointer user_data);
|
||||
NMPCacheOpsType nmp_cache_update_link_master_connected (NMPCache *cache, int ifindex, NMPObject **out_obj, gboolean *out_was_visible, NMPCachePreHook pre_hook, gpointer user_data);
|
||||
|
||||
NMPCache *nmp_cache_new (void);
|
||||
void nmp_cache_free (NMPCache *cache);
|
||||
|
||||
NMPObject *nmp_object_from_nl (NMPlatform *platform, const struct nl_object *nlo, gboolean id_only, gboolean complete_from_cache);
|
||||
struct nl_object *nmp_object_to_nl (NMPlatform *platform, const NMPObject *obj, gboolean id_only);
|
||||
|
||||
/* the following functions are currently implemented inside nm-linux-platform, because
|
||||
* they depend on utility functions there. */
|
||||
ObjectType _nlo_get_object_type (const struct nl_object *nlo);
|
||||
gboolean _nmp_vt_cmd_plobj_init_from_nl_link (NMPlatform *platform, NMPlatformObject *_obj, const struct nl_object *_nlo, gboolean id_only, gboolean complete_from_cache);
|
||||
gboolean _nmp_vt_cmd_plobj_init_from_nl_ip4_address (NMPlatform *platform, NMPlatformObject *_obj, const struct nl_object *_nlo, gboolean id_only, gboolean complete_from_cache);
|
||||
gboolean _nmp_vt_cmd_plobj_init_from_nl_ip6_address (NMPlatform *platform, NMPlatformObject *_obj, const struct nl_object *_nlo, gboolean id_only, gboolean complete_from_cache);
|
||||
gboolean _nmp_vt_cmd_plobj_init_from_nl_ip4_route (NMPlatform *platform, NMPlatformObject *_obj, const struct nl_object *_nlo, gboolean id_only, gboolean complete_from_cache);
|
||||
gboolean _nmp_vt_cmd_plobj_init_from_nl_ip6_route (NMPlatform *platform, NMPlatformObject *_obj, const struct nl_object *_nlo, gboolean id_only, gboolean complete_from_cache);
|
||||
struct nl_object *_nmp_vt_cmd_plobj_to_nl_link (NMPlatform *platform, const NMPlatformObject *_obj, gboolean id_only);
|
||||
struct nl_object *_nmp_vt_cmd_plobj_to_nl_ip4_address (NMPlatform *platform, const NMPlatformObject *_obj, gboolean id_only);
|
||||
struct nl_object *_nmp_vt_cmd_plobj_to_nl_ip6_address (NMPlatform *platform, const NMPlatformObject *_obj, gboolean id_only);
|
||||
struct nl_object *_nmp_vt_cmd_plobj_to_nl_ip4_route (NMPlatform *platform, const NMPlatformObject *_obj, gboolean id_only);
|
||||
struct nl_object *_nmp_vt_cmd_plobj_to_nl_ip6_route (NMPlatform *platform, const NMPlatformObject *_obj, gboolean id_only);
|
||||
|
||||
#endif /* __NMP_OBJECT_H__ */
|
||||
2
src/platform/tests/.gitignore
vendored
2
src/platform/tests/.gitignore
vendored
|
|
@ -8,5 +8,7 @@
|
|||
/test-general
|
||||
/test-link-fake
|
||||
/test-link-linux
|
||||
/test-nmp-object
|
||||
/test-route-fake
|
||||
/test-route-linux
|
||||
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ noinst_PROGRAMS = \
|
|||
test-address-fake \
|
||||
test-address-linux \
|
||||
test-general \
|
||||
test-nmp-object \
|
||||
test-route-fake \
|
||||
test-route-linux \
|
||||
test-cleanup-fake \
|
||||
|
|
@ -110,6 +111,11 @@ test_cleanup_linux_CPPFLAGS = \
|
|||
-DKERNEL_HACKS=1
|
||||
test_cleanup_linux_LDADD = $(PLATFORM_LDADD)
|
||||
|
||||
test_nmp_object_SOURCES = \
|
||||
test-nmp-object.c
|
||||
test_nmp_object_LDADD = \
|
||||
$(top_builddir)/src/libNetworkManager.la
|
||||
|
||||
test_general_SOURCES = \
|
||||
test-general.c
|
||||
test_general_LDADD = \
|
||||
|
|
@ -125,6 +131,7 @@ TESTS = \
|
|||
test-general \
|
||||
test-link-fake \
|
||||
test-link-linux \
|
||||
test-nmp-object \
|
||||
test-route-fake \
|
||||
test-route-linux
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include "nm-platform.h"
|
||||
#include "nm-linux-platform.h"
|
||||
#include "nm-fake-platform.h"
|
||||
#include "nm-macros-internal.h"
|
||||
|
||||
static void
|
||||
dump_interface (NMPlatformLink *link)
|
||||
|
|
@ -26,14 +27,14 @@ dump_interface (NMPlatformLink *link)
|
|||
size_t addrlen;
|
||||
int i;
|
||||
|
||||
g_assert (link->up || !link->connected);
|
||||
g_assert (NM_FLAGS_HAS (link->flags, IFF_UP) || !link->connected);
|
||||
|
||||
printf ("%d: %s: %s", link->ifindex, link->name, nm_link_type_to_string (link->type));
|
||||
if (link->up)
|
||||
if (NM_FLAGS_HAS (link->flags, IFF_UP))
|
||||
printf (" %s", link->connected ? "CONNECTED" : "DISCONNECTED");
|
||||
else
|
||||
printf (" DOWN");
|
||||
if (!link->arp)
|
||||
if (NM_FLAGS_HAS (link->flags, IFF_NOARP))
|
||||
printf (" noarp");
|
||||
if (link->master)
|
||||
printf (" master %d", link->master);
|
||||
|
|
@ -43,7 +44,7 @@ dump_interface (NMPlatformLink *link)
|
|||
printf ("\n");
|
||||
if (link->driver)
|
||||
printf (" driver: %s\n", link->driver);
|
||||
printf (" UDI: %s\n", link->udi);
|
||||
printf (" UDI: %s\n", nm_platform_link_get_udi (NM_PLATFORM_GET, link->ifindex));
|
||||
if (!nm_platform_vlan_get_info (NM_PLATFORM_GET, link->ifindex, &vlan_parent, &vlan_id))
|
||||
g_assert_not_reached ();
|
||||
if (vlan_parent)
|
||||
|
|
|
|||
|
|
@ -93,25 +93,25 @@ do_link_get_all (char **argv)
|
|||
static gboolean
|
||||
do_dummy_add (char **argv)
|
||||
{
|
||||
return nm_platform_dummy_add (NM_PLATFORM_GET, argv[0], NULL);
|
||||
return nm_platform_dummy_add (NM_PLATFORM_GET, argv[0], NULL) == NM_PLATFORM_ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
do_bridge_add (char **argv)
|
||||
{
|
||||
return nm_platform_bridge_add (NM_PLATFORM_GET, argv[0], NULL, 0, NULL);
|
||||
return nm_platform_bridge_add (NM_PLATFORM_GET, argv[0], NULL, 0, NULL) == NM_PLATFORM_ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
do_bond_add (char **argv)
|
||||
{
|
||||
return nm_platform_bond_add (NM_PLATFORM_GET, argv[0], NULL);
|
||||
return nm_platform_bond_add (NM_PLATFORM_GET, argv[0], NULL) == NM_PLATFORM_ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
do_team_add (char **argv)
|
||||
{
|
||||
return nm_platform_team_add (NM_PLATFORM_GET, argv[0], NULL);
|
||||
return nm_platform_team_add (NM_PLATFORM_GET, argv[0], NULL) == NM_PLATFORM_ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
@ -122,7 +122,7 @@ do_vlan_add (char **argv)
|
|||
int vlanid = strtol (*argv++, NULL, 10);
|
||||
guint32 vlan_flags = strtol (*argv++, NULL, 10);
|
||||
|
||||
return nm_platform_vlan_add (NM_PLATFORM_GET, name, parent, vlanid, vlan_flags, NULL);
|
||||
return nm_platform_vlan_add (NM_PLATFORM_GET, name, parent, vlanid, vlan_flags, NULL) == NM_PLATFORM_ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
@ -182,7 +182,14 @@ LINK_CMD_GET_FULL (get_type, decimal, value > 0)
|
|||
LINK_CMD_GET (is_software, boolean)
|
||||
LINK_CMD_GET (supports_slaves, boolean)
|
||||
|
||||
LINK_CMD (set_up)
|
||||
static gboolean
|
||||
do_link_set_up (char **argv)
|
||||
{
|
||||
int ifindex = parse_ifindex (argv[0]);
|
||||
|
||||
return ifindex ? nm_platform_link_set_up (NM_PLATFORM_GET, ifindex, NULL) : FALSE;
|
||||
}
|
||||
|
||||
LINK_CMD (set_down)
|
||||
LINK_CMD (set_arp)
|
||||
LINK_CMD (set_noarp)
|
||||
|
|
@ -858,7 +865,6 @@ main (int argc, char **argv)
|
|||
const char *arg0 = *argv++;
|
||||
const command_t *command = NULL;
|
||||
gboolean status = TRUE;
|
||||
int error;
|
||||
|
||||
#if !GLIB_CHECK_VERSION (2, 35, 0)
|
||||
g_type_init ();
|
||||
|
|
@ -892,12 +898,5 @@ main (int argc, char **argv)
|
|||
error ("\n");
|
||||
}
|
||||
|
||||
error = nm_platform_get_error (NM_PLATFORM_GET);
|
||||
if (error) {
|
||||
const char *msg = nm_platform_get_error_msg (NM_PLATFORM_GET);
|
||||
|
||||
error ("nm-platform: %s\n", msg);
|
||||
}
|
||||
|
||||
return !!error;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,22 +65,17 @@ test_ip4_address (void)
|
|||
|
||||
/* Add address */
|
||||
g_assert (!nm_platform_ip4_address_exists (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN));
|
||||
no_error ();
|
||||
g_assert (nm_platform_ip4_address_add (NM_PLATFORM_GET, ifindex, addr, 0, IP4_PLEN, lifetime, preferred, NULL));
|
||||
no_error ();
|
||||
g_assert (nm_platform_ip4_address_exists (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN));
|
||||
no_error ();
|
||||
accept_signal (address_added);
|
||||
|
||||
/* Add address again (aka update) */
|
||||
g_assert (nm_platform_ip4_address_add (NM_PLATFORM_GET, ifindex, addr, 0, IP4_PLEN, lifetime, preferred, NULL));
|
||||
no_error ();
|
||||
accept_signal (address_changed);
|
||||
accept_signals (address_changed, 0, 1);
|
||||
|
||||
/* Test address listing */
|
||||
addresses = nm_platform_ip4_address_get_all (NM_PLATFORM_GET, ifindex);
|
||||
g_assert (addresses);
|
||||
no_error ();
|
||||
g_assert_cmpint (addresses->len, ==, 1);
|
||||
address = &g_array_index (addresses, NMPlatformIP4Address, 0);
|
||||
g_assert_cmpint (address->ifindex, ==, ifindex);
|
||||
|
|
@ -90,13 +85,11 @@ test_ip4_address (void)
|
|||
|
||||
/* Remove address */
|
||||
g_assert (nm_platform_ip4_address_delete (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, 0));
|
||||
no_error ();
|
||||
g_assert (!nm_platform_ip4_address_exists (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN));
|
||||
accept_signal (address_removed);
|
||||
|
||||
/* Remove address again */
|
||||
g_assert (nm_platform_ip4_address_delete (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, 0));
|
||||
no_error ();
|
||||
|
||||
free_signal (address_added);
|
||||
free_signal (address_changed);
|
||||
|
|
@ -121,22 +114,17 @@ test_ip6_address (void)
|
|||
|
||||
/* Add address */
|
||||
g_assert (!nm_platform_ip6_address_exists (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN));
|
||||
no_error ();
|
||||
g_assert (nm_platform_ip6_address_add (NM_PLATFORM_GET, ifindex, addr, in6addr_any, IP6_PLEN, lifetime, preferred, flags));
|
||||
no_error ();
|
||||
g_assert (nm_platform_ip6_address_exists (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN));
|
||||
no_error ();
|
||||
accept_signal (address_added);
|
||||
|
||||
/* Add address again (aka update) */
|
||||
g_assert (nm_platform_ip6_address_add (NM_PLATFORM_GET, ifindex, addr, in6addr_any, IP6_PLEN, lifetime, preferred, flags));
|
||||
no_error ();
|
||||
accept_signal (address_changed);
|
||||
accept_signals (address_changed, 0, 1);
|
||||
|
||||
/* Test address listing */
|
||||
addresses = nm_platform_ip6_address_get_all (NM_PLATFORM_GET, ifindex);
|
||||
g_assert (addresses);
|
||||
no_error ();
|
||||
g_assert_cmpint (addresses->len, ==, 1);
|
||||
address = &g_array_index (addresses, NMPlatformIP6Address, 0);
|
||||
g_assert_cmpint (address->ifindex, ==, ifindex);
|
||||
|
|
@ -146,13 +134,11 @@ test_ip6_address (void)
|
|||
|
||||
/* Remove address */
|
||||
g_assert (nm_platform_ip6_address_delete (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN));
|
||||
no_error ();
|
||||
g_assert (!nm_platform_ip6_address_exists (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN));
|
||||
accept_signal (address_removed);
|
||||
|
||||
/* Remove address again */
|
||||
g_assert (nm_platform_ip6_address_delete (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN));
|
||||
no_error ();
|
||||
|
||||
free_signal (address_added);
|
||||
free_signal (address_changed);
|
||||
|
|
@ -175,7 +161,7 @@ test_ip4_address_external (void)
|
|||
/* Looks like addresses are not announced by kerenl when the interface
|
||||
* is down. Link-local IPv6 address is automatically added.
|
||||
*/
|
||||
g_assert (nm_platform_link_set_up (NM_PLATFORM_GET, nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME)));
|
||||
g_assert (nm_platform_link_set_up (NM_PLATFORM_GET, nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME), NULL));
|
||||
|
||||
/* Add/delete notification */
|
||||
run_command ("ip address add %s/%d dev %s valid_lft %d preferred_lft %d",
|
||||
|
|
@ -190,12 +176,10 @@ test_ip4_address_external (void)
|
|||
run_command ("ip address add %s/%d dev %s valid_lft %d preferred_lft %d",
|
||||
IP4_ADDRESS, IP4_PLEN, DEVICE_NAME, lifetime, preferred);
|
||||
g_assert (nm_platform_ip4_address_add (NM_PLATFORM_GET, ifindex, addr, 0, IP4_PLEN, lifetime, preferred, NULL));
|
||||
no_error ();
|
||||
g_assert (nm_platform_ip4_address_exists (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN));
|
||||
accept_signal (address_added);
|
||||
/*run_command ("ip address delete %s/%d dev %s", IP4_ADDRESS, IP4_PLEN, DEVICE_NAME);
|
||||
g_assert (nm_platform_ip4_address_delete (ifindex, addr, IP4_PLEN, 0));
|
||||
no_error ();
|
||||
g_assert (!nm_platform_ip4_address_exists (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN));
|
||||
accept_signal (address_removed);*/
|
||||
|
||||
|
|
@ -229,12 +213,10 @@ test_ip6_address_external (void)
|
|||
run_command ("ip address add %s/%d dev %s valid_lft %d preferred_lft %d",
|
||||
IP6_ADDRESS, IP6_PLEN, DEVICE_NAME, lifetime, preferred);
|
||||
g_assert (nm_platform_ip6_address_add (NM_PLATFORM_GET, ifindex, addr, in6addr_any, IP6_PLEN, lifetime, preferred, flags));
|
||||
no_error ();
|
||||
g_assert (nm_platform_ip6_address_exists (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN));
|
||||
accept_signal (address_added);
|
||||
/*run_command ("ip address delete %s/%d dev %s", IP6_ADDRESS, IP6_PLEN, DEVICE_NAME);
|
||||
g_assert (nm_platform_ip6_address_delete (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN));
|
||||
no_error ();
|
||||
g_assert (!nm_platform_ip6_address_exists (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN));
|
||||
wait_signal (address_removed);*/
|
||||
|
||||
|
|
@ -255,7 +237,7 @@ setup_tests (void)
|
|||
|
||||
nm_platform_link_delete (NM_PLATFORM_GET, nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME));
|
||||
g_assert (!nm_platform_link_exists (NM_PLATFORM_GET, DEVICE_NAME));
|
||||
g_assert (nm_platform_dummy_add (NM_PLATFORM_GET, DEVICE_NAME, NULL));
|
||||
g_assert (nm_platform_dummy_add (NM_PLATFORM_GET, DEVICE_NAME, NULL) == NM_PLATFORM_ERROR_SUCCESS);
|
||||
accept_signal (link_added);
|
||||
free_signal (link_added);
|
||||
|
||||
|
|
|
|||
|
|
@ -35,10 +35,10 @@ test_cleanup_internal (void)
|
|||
inet_pton (AF_INET6, "2001:db8:e:f:1:2:3:4", &gateway6);
|
||||
|
||||
/* Create and set up device */
|
||||
g_assert (nm_platform_dummy_add (NM_PLATFORM_GET, DEVICE_NAME, NULL));
|
||||
g_assert (nm_platform_dummy_add (NM_PLATFORM_GET, DEVICE_NAME, NULL) == NM_PLATFORM_ERROR_SUCCESS);
|
||||
accept_signal (link_added);
|
||||
free_signal (link_added);
|
||||
g_assert (nm_platform_link_set_up (NM_PLATFORM_GET, nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME)));
|
||||
g_assert (nm_platform_link_set_up (NM_PLATFORM_GET, nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME), NULL));
|
||||
ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME);
|
||||
g_assert (ifindex > 0);
|
||||
|
||||
|
|
@ -58,7 +58,7 @@ test_cleanup_internal (void)
|
|||
routes6 = nm_platform_ip6_route_get_all (NM_PLATFORM_GET, ifindex, NM_PLATFORM_GET_ROUTE_MODE_ALL);
|
||||
|
||||
g_assert_cmpint (addresses4->len, ==, 1);
|
||||
g_assert_cmpint (addresses6->len, ==, 1);
|
||||
g_assert_cmpint (addresses6->len, ==, 2); /* also has a IPv6 LL address. */
|
||||
g_assert_cmpint (routes4->len, ==, 3);
|
||||
g_assert_cmpint (routes6->len, ==, 3);
|
||||
|
||||
|
|
|
|||
|
|
@ -15,9 +15,6 @@
|
|||
|
||||
#define debug(...) nm_log_dbg (LOGD_PLATFORM, __VA_ARGS__)
|
||||
|
||||
#define error(err) g_assert (nm_platform_get_error (NM_PLATFORM_GET) == err)
|
||||
#define no_error() error (NM_PLATFORM_ERROR_NONE)
|
||||
|
||||
typedef struct {
|
||||
int handler_id;
|
||||
const char *name;
|
||||
|
|
|
|||
|
|
@ -20,11 +20,24 @@
|
|||
|
||||
#include "nm-platform-utils.h"
|
||||
|
||||
#include <linux/rtnetlink.h>
|
||||
|
||||
#include "nm-linux-platform.h"
|
||||
#include "nm-logging.h"
|
||||
|
||||
#include "nm-test-utils.h"
|
||||
|
||||
|
||||
/******************************************************************/
|
||||
|
||||
static void
|
||||
test_init_linux_platform ()
|
||||
{
|
||||
gs_unref_object NMPlatform *platform = NULL;
|
||||
|
||||
platform = g_object_new (NM_TYPE_LINUX_PLATFORM, NULL);
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
|
||||
NMTST_DEFINE ();
|
||||
|
|
@ -34,5 +47,7 @@ main (int argc, char **argv)
|
|||
{
|
||||
nmtst_init_assert_logging (&argc, &argv, "INFO", "DEFAULT");
|
||||
|
||||
g_test_add_func ("/general/init_linux_platform", test_init_linux_platform);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,54 +22,32 @@ test_bogus(void)
|
|||
size_t addrlen;
|
||||
|
||||
g_assert (!nm_platform_link_exists (NM_PLATFORM_GET, BOGUS_NAME));
|
||||
no_error ();
|
||||
g_assert (!nm_platform_link_delete (NM_PLATFORM_GET, BOGUS_IFINDEX));
|
||||
error (NM_PLATFORM_ERROR_NOT_FOUND);
|
||||
g_assert (!nm_platform_link_get_ifindex (NM_PLATFORM_GET, BOGUS_NAME));
|
||||
error (NM_PLATFORM_ERROR_NOT_FOUND);
|
||||
g_assert (!nm_platform_link_get_name (NM_PLATFORM_GET, BOGUS_IFINDEX));
|
||||
error (NM_PLATFORM_ERROR_NOT_FOUND);
|
||||
g_assert (!nm_platform_link_get_type (NM_PLATFORM_GET, BOGUS_IFINDEX));
|
||||
error (NM_PLATFORM_ERROR_NOT_FOUND);
|
||||
g_assert (!nm_platform_link_get_type_name (NM_PLATFORM_GET, BOGUS_IFINDEX));
|
||||
error (NM_PLATFORM_ERROR_NOT_FOUND);
|
||||
|
||||
g_assert (!nm_platform_link_set_up (NM_PLATFORM_GET, BOGUS_IFINDEX));
|
||||
error (NM_PLATFORM_ERROR_NOT_FOUND);
|
||||
g_assert (!nm_platform_link_set_up (NM_PLATFORM_GET, BOGUS_IFINDEX, NULL));
|
||||
g_assert (!nm_platform_link_set_down (NM_PLATFORM_GET, BOGUS_IFINDEX));
|
||||
error (NM_PLATFORM_ERROR_NOT_FOUND);
|
||||
g_assert (!nm_platform_link_set_arp (NM_PLATFORM_GET, BOGUS_IFINDEX));
|
||||
error (NM_PLATFORM_ERROR_NOT_FOUND);
|
||||
g_assert (!nm_platform_link_set_noarp (NM_PLATFORM_GET, BOGUS_IFINDEX));
|
||||
error (NM_PLATFORM_ERROR_NOT_FOUND);
|
||||
g_assert (!nm_platform_link_is_up (NM_PLATFORM_GET, BOGUS_IFINDEX));
|
||||
error (NM_PLATFORM_ERROR_NOT_FOUND);
|
||||
g_assert (!nm_platform_link_is_connected (NM_PLATFORM_GET, BOGUS_IFINDEX));
|
||||
error (NM_PLATFORM_ERROR_NOT_FOUND);
|
||||
g_assert (!nm_platform_link_uses_arp (NM_PLATFORM_GET, BOGUS_IFINDEX));
|
||||
error (NM_PLATFORM_ERROR_NOT_FOUND);
|
||||
|
||||
g_assert (!nm_platform_link_get_address (NM_PLATFORM_GET, BOGUS_IFINDEX, &addrlen));
|
||||
g_assert (!addrlen);
|
||||
error (NM_PLATFORM_ERROR_NOT_FOUND);
|
||||
g_assert (!nm_platform_link_get_address (NM_PLATFORM_GET, BOGUS_IFINDEX, NULL));
|
||||
error (NM_PLATFORM_ERROR_NOT_FOUND);
|
||||
g_assert (!nm_platform_link_set_mtu (NM_PLATFORM_GET, BOGUS_IFINDEX, MTU));
|
||||
error (NM_PLATFORM_ERROR_NOT_FOUND);
|
||||
g_assert (!nm_platform_link_get_mtu (NM_PLATFORM_GET, BOGUS_IFINDEX));
|
||||
error (NM_PLATFORM_ERROR_NOT_FOUND);
|
||||
|
||||
g_assert (!nm_platform_link_supports_carrier_detect (NM_PLATFORM_GET, BOGUS_IFINDEX));
|
||||
error (NM_PLATFORM_ERROR_NOT_FOUND);
|
||||
g_assert (!nm_platform_link_supports_vlans (NM_PLATFORM_GET, BOGUS_IFINDEX));
|
||||
error (NM_PLATFORM_ERROR_NOT_FOUND);
|
||||
|
||||
g_assert (!nm_platform_vlan_get_info (NM_PLATFORM_GET, BOGUS_IFINDEX, NULL, NULL));
|
||||
error (NM_PLATFORM_ERROR_NOT_FOUND);
|
||||
g_assert (!nm_platform_vlan_set_ingress_map (NM_PLATFORM_GET, BOGUS_IFINDEX, 0, 0));
|
||||
error (NM_PLATFORM_ERROR_NOT_FOUND);
|
||||
g_assert (!nm_platform_vlan_set_egress_map (NM_PLATFORM_GET, BOGUS_IFINDEX, 0, 0));
|
||||
error (NM_PLATFORM_ERROR_NOT_FOUND);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -85,48 +63,52 @@ test_loopback (void)
|
|||
g_assert (!nm_platform_link_supports_vlans (NM_PLATFORM_GET, LO_INDEX));
|
||||
}
|
||||
|
||||
static int
|
||||
static gboolean
|
||||
software_add (NMLinkType link_type, const char *name)
|
||||
{
|
||||
switch (link_type) {
|
||||
case NM_LINK_TYPE_DUMMY:
|
||||
return nm_platform_dummy_add (NM_PLATFORM_GET, name, NULL);
|
||||
return nm_platform_dummy_add (NM_PLATFORM_GET, name, NULL) == NM_PLATFORM_ERROR_SUCCESS;
|
||||
case NM_LINK_TYPE_BRIDGE:
|
||||
return nm_platform_bridge_add (NM_PLATFORM_GET, name, NULL, 0, NULL);
|
||||
return nm_platform_bridge_add (NM_PLATFORM_GET, name, NULL, 0, NULL) == NM_PLATFORM_ERROR_SUCCESS;
|
||||
case NM_LINK_TYPE_BOND:
|
||||
{
|
||||
gboolean bond0_exists = nm_platform_link_exists (NM_PLATFORM_GET, "bond0");
|
||||
gboolean result = nm_platform_bond_add (NM_PLATFORM_GET, name, NULL);
|
||||
NMPlatformError error = nm_platform_get_error (NM_PLATFORM_GET);
|
||||
NMPlatformError plerr;
|
||||
|
||||
plerr = nm_platform_bond_add (NM_PLATFORM_GET, name, NULL);
|
||||
|
||||
/* Check that bond0 is *not* automatically created. */
|
||||
if (!bond0_exists)
|
||||
g_assert (!nm_platform_link_exists (NM_PLATFORM_GET, "bond0"));
|
||||
|
||||
nm_platform_set_error (NM_PLATFORM_GET, error);
|
||||
return result;
|
||||
return plerr == NM_PLATFORM_ERROR_SUCCESS;
|
||||
}
|
||||
case NM_LINK_TYPE_TEAM:
|
||||
return nm_platform_team_add (NM_PLATFORM_GET, name, NULL);
|
||||
return nm_platform_team_add (NM_PLATFORM_GET, name, NULL) == NM_PLATFORM_ERROR_SUCCESS;
|
||||
case NM_LINK_TYPE_VLAN: {
|
||||
SignalData *parent_added;
|
||||
SignalData *parent_changed;
|
||||
|
||||
/* Don't call link_callback for the bridge interface */
|
||||
parent_added = add_signal_ifname (NM_PLATFORM_SIGNAL_LINK_CHANGED, NM_PLATFORM_SIGNAL_ADDED, link_callback, PARENT_NAME);
|
||||
if (nm_platform_bridge_add (NM_PLATFORM_GET, PARENT_NAME, NULL, 0, NULL))
|
||||
if (nm_platform_bridge_add (NM_PLATFORM_GET, PARENT_NAME, NULL, 0, NULL) == NM_PLATFORM_ERROR_SUCCESS)
|
||||
accept_signal (parent_added);
|
||||
free_signal (parent_added);
|
||||
|
||||
{
|
||||
int parent_ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, PARENT_NAME);
|
||||
gboolean was_up = nm_platform_link_is_up (NM_PLATFORM_GET, parent_ifindex);
|
||||
|
||||
parent_changed = add_signal_ifindex (NM_PLATFORM_SIGNAL_LINK_CHANGED, NM_PLATFORM_SIGNAL_CHANGED, link_callback, parent_ifindex);
|
||||
g_assert (nm_platform_link_set_up (NM_PLATFORM_GET, parent_ifindex));
|
||||
accept_signal (parent_changed);
|
||||
g_assert (nm_platform_link_set_up (NM_PLATFORM_GET, parent_ifindex, NULL));
|
||||
if (was_up) {
|
||||
/* when NM is running in the background, it will mess with addrgenmode which might cause additional signals. */
|
||||
accept_signals (parent_changed, 0, 1);
|
||||
} else
|
||||
accept_signal (parent_changed);
|
||||
free_signal (parent_changed);
|
||||
|
||||
return nm_platform_vlan_add (NM_PLATFORM_GET, name, parent_ifindex, VLAN_ID, 0, NULL);
|
||||
return nm_platform_vlan_add (NM_PLATFORM_GET, name, parent_ifindex, VLAN_ID, 0, NULL) == NM_PLATFORM_ERROR_SUCCESS;
|
||||
}
|
||||
}
|
||||
default:
|
||||
|
|
@ -142,6 +124,9 @@ test_slave (int master, int type, SignalData *master_changed)
|
|||
SignalData *link_added = add_signal_ifname (NM_PLATFORM_SIGNAL_LINK_CHANGED, NM_PLATFORM_SIGNAL_ADDED, link_callback, SLAVE_NAME);
|
||||
SignalData *link_changed, *link_removed;
|
||||
char *value;
|
||||
NMLinkType link_type = nm_platform_link_get_type (NM_PLATFORM_GET, master);
|
||||
|
||||
g_assert (NM_IN_SET (link_type, NM_LINK_TYPE_TEAM, NM_LINK_TYPE_BOND, NM_LINK_TYPE_BRIDGE));
|
||||
|
||||
g_assert (software_add (type, SLAVE_NAME));
|
||||
ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, SLAVE_NAME);
|
||||
|
|
@ -154,20 +139,29 @@ test_slave (int master, int type, SignalData *master_changed)
|
|||
*
|
||||
* See https://bugzilla.redhat.com/show_bug.cgi?id=910348
|
||||
*/
|
||||
g_assert (!nm_platform_link_is_up (NM_PLATFORM_GET, ifindex));
|
||||
g_assert (nm_platform_link_set_down (NM_PLATFORM_GET, ifindex));
|
||||
g_assert (!nm_platform_link_is_up (NM_PLATFORM_GET, ifindex));
|
||||
accept_signal (link_changed);
|
||||
ensure_no_signal (link_changed);
|
||||
|
||||
/* Enslave */
|
||||
link_changed->ifindex = ifindex;
|
||||
g_assert (nm_platform_link_enslave (NM_PLATFORM_GET, master, ifindex)); no_error ();
|
||||
g_assert_cmpint (nm_platform_link_get_master (NM_PLATFORM_GET, ifindex), ==, master); no_error ();
|
||||
accept_signal (link_changed);
|
||||
accept_signal (master_changed);
|
||||
g_assert (nm_platform_link_enslave (NM_PLATFORM_GET, master, ifindex));
|
||||
g_assert_cmpint (nm_platform_link_get_master (NM_PLATFORM_GET, ifindex), ==, master);
|
||||
|
||||
accept_signals (link_changed, 1, 3);
|
||||
accept_signals (master_changed, 0, 1);
|
||||
|
||||
/* enslaveing brings put the slave */
|
||||
if (NM_IN_SET (link_type, NM_LINK_TYPE_BOND, NM_LINK_TYPE_TEAM))
|
||||
g_assert (nm_platform_link_is_up (NM_PLATFORM_GET, ifindex));
|
||||
else
|
||||
g_assert (!nm_platform_link_is_up (NM_PLATFORM_GET, ifindex));
|
||||
|
||||
/* Set master up */
|
||||
g_assert (nm_platform_link_set_up (NM_PLATFORM_GET, master));
|
||||
accept_signal (master_changed);
|
||||
g_assert (nm_platform_link_set_up (NM_PLATFORM_GET, master, NULL));
|
||||
g_assert (nm_platform_link_is_up (NM_PLATFORM_GET, master));
|
||||
accept_signals (master_changed, 1, 2);
|
||||
|
||||
/* Master with a disconnected slave is disconnected
|
||||
*
|
||||
|
|
@ -179,7 +173,7 @@ test_slave (int master, int type, SignalData *master_changed)
|
|||
case NM_LINK_TYPE_TEAM:
|
||||
g_assert (nm_platform_link_set_down (NM_PLATFORM_GET, ifindex));
|
||||
accept_signal (link_changed);
|
||||
accept_signal (master_changed);
|
||||
accept_signals (master_changed, 0, 2);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
@ -202,28 +196,28 @@ test_slave (int master, int type, SignalData *master_changed)
|
|||
}
|
||||
|
||||
/* Set slave up and see if master gets up too */
|
||||
g_assert (nm_platform_link_set_up (NM_PLATFORM_GET, ifindex)); no_error ();
|
||||
g_assert (nm_platform_link_set_up (NM_PLATFORM_GET, ifindex, NULL));
|
||||
g_assert (nm_platform_link_is_connected (NM_PLATFORM_GET, ifindex));
|
||||
g_assert (nm_platform_link_is_connected (NM_PLATFORM_GET, master));
|
||||
accept_signal (link_changed);
|
||||
accept_signal (master_changed);
|
||||
accept_signals (link_changed, 1, 3);
|
||||
/* NM running, can cause additional change of addrgenmode */
|
||||
accept_signals (master_changed, 1, 2);
|
||||
|
||||
/* Enslave again
|
||||
*
|
||||
* Gracefully succeed if already enslaved.
|
||||
*/
|
||||
g_assert (nm_platform_link_enslave (NM_PLATFORM_GET, master, ifindex)); no_error ();
|
||||
accept_signal (link_changed);
|
||||
accept_signal (master_changed);
|
||||
ensure_no_signal (link_changed);
|
||||
g_assert (nm_platform_link_enslave (NM_PLATFORM_GET, master, ifindex));
|
||||
accept_signals (link_changed, 0, 2);
|
||||
ensure_no_signal (master_changed);
|
||||
|
||||
/* Set slave option */
|
||||
switch (type) {
|
||||
case NM_LINK_TYPE_BRIDGE:
|
||||
if (nmtst_platform_is_sysfs_writable ()) {
|
||||
g_assert (nm_platform_slave_set_option (NM_PLATFORM_GET, ifindex, "priority", "789"));
|
||||
no_error ();
|
||||
value = nm_platform_slave_get_option (NM_PLATFORM_GET, ifindex, "priority");
|
||||
no_error ();
|
||||
g_assert_cmpstr (value, ==, "789");
|
||||
g_free (value);
|
||||
}
|
||||
|
|
@ -233,18 +227,28 @@ test_slave (int master, int type, SignalData *master_changed)
|
|||
}
|
||||
|
||||
/* Release */
|
||||
ensure_no_signal (link_changed);
|
||||
g_assert (nm_platform_link_release (NM_PLATFORM_GET, master, ifindex));
|
||||
g_assert_cmpint (nm_platform_link_get_master (NM_PLATFORM_GET, ifindex), ==, 0); no_error ();
|
||||
accept_signal (link_changed);
|
||||
accept_signal (master_changed);
|
||||
g_assert_cmpint (nm_platform_link_get_master (NM_PLATFORM_GET, ifindex), ==, 0);
|
||||
accept_signals (link_changed, 1, 3);
|
||||
if (link_type != NM_LINK_TYPE_TEAM)
|
||||
accept_signals (master_changed, 1, 2);
|
||||
else
|
||||
accept_signals (master_changed, 1, 1);
|
||||
|
||||
ensure_no_signal (master_changed);
|
||||
|
||||
/* Release again */
|
||||
ensure_no_signal (link_changed);
|
||||
g_assert (!nm_platform_link_release (NM_PLATFORM_GET, master, ifindex));
|
||||
error (NM_PLATFORM_ERROR_NOT_SLAVE);
|
||||
|
||||
ensure_no_signal (master_changed);
|
||||
|
||||
/* Remove */
|
||||
ensure_no_signal (link_changed);
|
||||
g_assert (nm_platform_link_delete (NM_PLATFORM_GET, ifindex));
|
||||
no_error ();
|
||||
accept_signals (master_changed, 0, 1);
|
||||
accept_signals (link_changed, 0, 1);
|
||||
accept_signal (link_removed);
|
||||
|
||||
free_signal (link_added);
|
||||
|
|
@ -264,7 +268,6 @@ test_software (NMLinkType link_type, const char *link_typename)
|
|||
/* Add */
|
||||
link_added = add_signal_ifname (NM_PLATFORM_SIGNAL_LINK_CHANGED, NM_PLATFORM_SIGNAL_ADDED, link_callback, DEVICE_NAME);
|
||||
g_assert (software_add (link_type, DEVICE_NAME));
|
||||
no_error ();
|
||||
accept_signal (link_added);
|
||||
g_assert (nm_platform_link_exists (NM_PLATFORM_GET, DEVICE_NAME));
|
||||
ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME);
|
||||
|
|
@ -277,18 +280,16 @@ test_software (NMLinkType link_type, const char *link_typename)
|
|||
g_assert (nm_platform_vlan_get_info (NM_PLATFORM_GET, ifindex, &vlan_parent, &vlan_id));
|
||||
g_assert_cmpint (vlan_parent, ==, nm_platform_link_get_ifindex (NM_PLATFORM_GET, PARENT_NAME));
|
||||
g_assert_cmpint (vlan_id, ==, VLAN_ID);
|
||||
no_error ();
|
||||
}
|
||||
|
||||
/* Add again */
|
||||
g_assert (!software_add (link_type, DEVICE_NAME));
|
||||
error (NM_PLATFORM_ERROR_EXISTS);
|
||||
|
||||
/* Set ARP/NOARP */
|
||||
g_assert (nm_platform_link_uses_arp (NM_PLATFORM_GET, ifindex));
|
||||
g_assert (nm_platform_link_set_noarp (NM_PLATFORM_GET, ifindex));
|
||||
g_assert (!nm_platform_link_uses_arp (NM_PLATFORM_GET, ifindex));
|
||||
accept_signal (link_changed);
|
||||
accept_signals (link_changed, 1, 2);
|
||||
g_assert (nm_platform_link_set_arp (NM_PLATFORM_GET, ifindex));
|
||||
g_assert (nm_platform_link_uses_arp (NM_PLATFORM_GET, ifindex));
|
||||
accept_signal (link_changed);
|
||||
|
|
@ -298,9 +299,7 @@ test_software (NMLinkType link_type, const char *link_typename)
|
|||
case NM_LINK_TYPE_BRIDGE:
|
||||
if (nmtst_platform_is_sysfs_writable ()) {
|
||||
g_assert (nm_platform_master_set_option (NM_PLATFORM_GET, ifindex, "forward_delay", "789"));
|
||||
no_error ();
|
||||
value = nm_platform_master_get_option (NM_PLATFORM_GET, ifindex, "forward_delay");
|
||||
no_error ();
|
||||
g_assert_cmpstr (value, ==, "789");
|
||||
g_free (value);
|
||||
}
|
||||
|
|
@ -308,9 +307,7 @@ test_software (NMLinkType link_type, const char *link_typename)
|
|||
case NM_LINK_TYPE_BOND:
|
||||
if (nmtst_platform_is_sysfs_writable ()) {
|
||||
g_assert (nm_platform_master_set_option (NM_PLATFORM_GET, ifindex, "mode", "active-backup"));
|
||||
no_error ();
|
||||
value = nm_platform_master_get_option (NM_PLATFORM_GET, ifindex, "mode");
|
||||
no_error ();
|
||||
/* When reading back, the output looks slightly different. */
|
||||
g_assert (g_str_has_prefix (value, "active-backup"));
|
||||
g_free (value);
|
||||
|
|
@ -332,20 +329,17 @@ test_software (NMLinkType link_type, const char *link_typename)
|
|||
default:
|
||||
break;
|
||||
}
|
||||
free_signal (link_changed);
|
||||
|
||||
/* Delete */
|
||||
g_assert (nm_platform_link_delete (NM_PLATFORM_GET, ifindex));
|
||||
no_error ();
|
||||
g_assert (!nm_platform_link_exists (NM_PLATFORM_GET, DEVICE_NAME)); no_error ();
|
||||
g_assert (!nm_platform_link_exists (NM_PLATFORM_GET, DEVICE_NAME));
|
||||
g_assert_cmpint (nm_platform_link_get_type (NM_PLATFORM_GET, ifindex), ==, NM_LINK_TYPE_NONE);
|
||||
error (NM_PLATFORM_ERROR_NOT_FOUND);
|
||||
g_assert (!nm_platform_link_get_type (NM_PLATFORM_GET, ifindex));
|
||||
error (NM_PLATFORM_ERROR_NOT_FOUND);
|
||||
accept_signal (link_removed);
|
||||
|
||||
/* Delete again */
|
||||
g_assert (!nm_platform_link_delete (NM_PLATFORM_GET, nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME)));
|
||||
error (NM_PLATFORM_ERROR_NOT_FOUND);
|
||||
|
||||
/* VLAN: Delete parent */
|
||||
if (link_type == NM_LINK_TYPE_VLAN) {
|
||||
|
|
@ -358,7 +352,6 @@ test_software (NMLinkType link_type, const char *link_typename)
|
|||
|
||||
/* No pending signal */
|
||||
free_signal (link_added);
|
||||
free_signal (link_changed);
|
||||
free_signal (link_removed);
|
||||
}
|
||||
|
||||
|
|
@ -404,18 +397,15 @@ test_internal (void)
|
|||
int ifindex;
|
||||
|
||||
/* Check the functions for non-existent devices */
|
||||
g_assert (!nm_platform_link_exists (NM_PLATFORM_GET, DEVICE_NAME)); no_error ();
|
||||
g_assert (!nm_platform_link_exists (NM_PLATFORM_GET, DEVICE_NAME));
|
||||
g_assert (!nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME));
|
||||
error (NM_PLATFORM_ERROR_NOT_FOUND);
|
||||
|
||||
/* Add device */
|
||||
g_assert (nm_platform_dummy_add (NM_PLATFORM_GET, DEVICE_NAME, NULL));
|
||||
no_error ();
|
||||
g_assert (nm_platform_dummy_add (NM_PLATFORM_GET, DEVICE_NAME, NULL) == NM_PLATFORM_ERROR_SUCCESS);
|
||||
accept_signal (link_added);
|
||||
|
||||
/* Try to add again */
|
||||
g_assert (!nm_platform_dummy_add (NM_PLATFORM_GET, DEVICE_NAME, NULL));
|
||||
error (NM_PLATFORM_ERROR_EXISTS);
|
||||
g_assert (nm_platform_dummy_add (NM_PLATFORM_GET, DEVICE_NAME, NULL) == NM_PLATFORM_ERROR_EXISTS);
|
||||
|
||||
/* Check device index, name and type */
|
||||
ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME);
|
||||
|
|
@ -427,15 +417,15 @@ test_internal (void)
|
|||
link_removed = add_signal_ifindex (NM_PLATFORM_SIGNAL_LINK_CHANGED, NM_PLATFORM_SIGNAL_REMOVED, link_callback, ifindex);
|
||||
|
||||
/* Up/connected */
|
||||
g_assert (!nm_platform_link_is_up (NM_PLATFORM_GET, ifindex)); no_error ();
|
||||
g_assert (!nm_platform_link_is_connected (NM_PLATFORM_GET, ifindex)); no_error ();
|
||||
g_assert (nm_platform_link_set_up (NM_PLATFORM_GET, ifindex)); no_error ();
|
||||
g_assert (nm_platform_link_is_up (NM_PLATFORM_GET, ifindex)); no_error ();
|
||||
g_assert (nm_platform_link_is_connected (NM_PLATFORM_GET, ifindex)); no_error ();
|
||||
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_set_up (NM_PLATFORM_GET, ifindex, NULL));
|
||||
g_assert (nm_platform_link_is_up (NM_PLATFORM_GET, ifindex));
|
||||
g_assert (nm_platform_link_is_connected (NM_PLATFORM_GET, ifindex));
|
||||
accept_signal (link_changed);
|
||||
g_assert (nm_platform_link_set_down (NM_PLATFORM_GET, ifindex)); no_error ();
|
||||
g_assert (!nm_platform_link_is_up (NM_PLATFORM_GET, ifindex)); no_error ();
|
||||
g_assert (!nm_platform_link_is_connected (NM_PLATFORM_GET, ifindex)); no_error ();
|
||||
g_assert (nm_platform_link_set_down (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));
|
||||
accept_signal (link_changed);
|
||||
|
||||
/* arp/noarp */
|
||||
|
|
@ -462,18 +452,15 @@ test_internal (void)
|
|||
|
||||
/* Set MTU */
|
||||
g_assert (nm_platform_link_set_mtu (NM_PLATFORM_GET, ifindex, MTU));
|
||||
no_error ();
|
||||
g_assert_cmpint (nm_platform_link_get_mtu (NM_PLATFORM_GET, ifindex), ==, MTU);
|
||||
accept_signal (link_changed);
|
||||
|
||||
/* Delete device */
|
||||
g_assert (nm_platform_link_delete (NM_PLATFORM_GET, ifindex));
|
||||
no_error ();
|
||||
accept_signal (link_removed);
|
||||
|
||||
/* Try to delete again */
|
||||
g_assert (!nm_platform_link_delete (NM_PLATFORM_GET, ifindex));
|
||||
error (NM_PLATFORM_ERROR_NOT_FOUND);
|
||||
|
||||
free_signal (link_added);
|
||||
free_signal (link_changed);
|
||||
|
|
@ -522,23 +509,17 @@ test_external (void)
|
|||
wait_signal (link_changed);
|
||||
g_assert (!nm_platform_link_is_up (NM_PLATFORM_GET, ifindex));
|
||||
g_assert (!nm_platform_link_is_connected (NM_PLATFORM_GET, ifindex));
|
||||
/* This test doesn't trigger a netlink event at least on
|
||||
* 3.8.2-206.fc18.x86_64. Disabling the waiting and checking code
|
||||
* because of that.
|
||||
*/
|
||||
|
||||
run_command ("ip link set %s arp on", DEVICE_NAME);
|
||||
#if 0
|
||||
wait_signal (link_changed);
|
||||
g_assert (nm_platform_link_uses_arp (ifindex));
|
||||
#endif
|
||||
g_assert (nm_platform_link_uses_arp (NM_PLATFORM_GET, ifindex));
|
||||
run_command ("ip link set %s arp off", DEVICE_NAME);
|
||||
#if 0
|
||||
wait_signal (link_changed);
|
||||
g_assert (!nm_platform_link_uses_arp (ifindex));
|
||||
#endif
|
||||
g_assert (!nm_platform_link_uses_arp (NM_PLATFORM_GET, ifindex));
|
||||
|
||||
run_command ("ip link del %s", DEVICE_NAME);
|
||||
wait_signal (link_removed);
|
||||
accept_signals (link_changed, 0, 1);
|
||||
g_assert (!nm_platform_link_exists (NM_PLATFORM_GET, DEVICE_NAME));
|
||||
|
||||
free_signal (link_added);
|
||||
|
|
|
|||
426
src/platform/tests/test-nmp-object.c
Normal file
426
src/platform/tests/test-nmp-object.c
Normal file
|
|
@ -0,0 +1,426 @@
|
|||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
||||
/* nm-platform.c - Handle runtime kernel networking configuration
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Copyright (C) 2015 Red Hat, Inc.
|
||||
*/
|
||||
|
||||
#include "nmp-object.h"
|
||||
|
||||
#include "nm-logging.h"
|
||||
|
||||
#include "nm-test-utils.h"
|
||||
|
||||
struct {
|
||||
GList *udev_devices;
|
||||
} global;
|
||||
|
||||
/******************************************************************/
|
||||
|
||||
static gboolean
|
||||
_nmp_object_id_equal (const NMPObject *a, const NMPObject *b)
|
||||
{
|
||||
gboolean a_b = nmp_object_id_equal (a, b);
|
||||
|
||||
g_assert (NM_IN_SET (a_b, FALSE, TRUE) && a_b == nmp_object_id_equal (b, a));
|
||||
return a_b;
|
||||
}
|
||||
#define nmp_object_id_equal _nmp_object_id_equal
|
||||
|
||||
static gboolean
|
||||
_nmp_object_equal (const NMPObject *a, const NMPObject *b)
|
||||
{
|
||||
gboolean a_b = nmp_object_equal (a, b);
|
||||
|
||||
g_assert (NM_IN_SET (a_b, FALSE, TRUE) && a_b == nmp_object_equal (b, a));
|
||||
return a_b;
|
||||
}
|
||||
#define nmp_object_equal _nmp_object_equal
|
||||
|
||||
/******************************************************************/
|
||||
|
||||
static void
|
||||
_assert_cache_multi_lookup_contains (const NMPCache *cache, const NMPCacheId *cache_id, const NMPObject *obj, gboolean contains)
|
||||
{
|
||||
const NMPlatformObject *const *objects;
|
||||
guint i, len;
|
||||
gboolean found;
|
||||
|
||||
g_assert (cache_id);
|
||||
g_assert (NMP_OBJECT_IS_VALID (obj));
|
||||
|
||||
g_assert (nmp_cache_lookup_obj (cache, obj) == obj);
|
||||
|
||||
objects = nmp_cache_lookup_multi (cache, cache_id, &len);
|
||||
|
||||
g_assert ((len == 0 && !objects) || (len > 0 && objects && !objects[len]));
|
||||
|
||||
found = FALSE;
|
||||
for (i = 0; i < len; i++) {
|
||||
NMPObject *o;
|
||||
|
||||
g_assert (objects[i]);
|
||||
o = NMP_OBJECT_UP_CAST (objects[i]);
|
||||
g_assert (NMP_OBJECT_IS_VALID (o));
|
||||
|
||||
if (obj == o) {
|
||||
g_assert (!found);
|
||||
found = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
g_assert (!!contains == found);
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
|
||||
typedef struct {
|
||||
NMPCache *cache;
|
||||
NMPCacheOpsType expected_ops_type;
|
||||
const NMPObject *obj_clone;
|
||||
NMPObject *new_clone;
|
||||
gboolean was_visible;
|
||||
gboolean called;
|
||||
} _NMPCacheUpdateData;
|
||||
|
||||
static void
|
||||
_nmp_cache_update_hook (NMPCache *cache, const NMPObject *old, const NMPObject *new, NMPCacheOpsType ops_type, gpointer user_data)
|
||||
{
|
||||
_NMPCacheUpdateData *data = user_data;
|
||||
|
||||
g_assert (data);
|
||||
g_assert (!data->called);
|
||||
g_assert (data->cache == cache);
|
||||
|
||||
g_assert_cmpint (data->expected_ops_type, ==, ops_type);
|
||||
|
||||
switch (ops_type) {
|
||||
case NMP_CACHE_OPS_ADDED:
|
||||
g_assert (!old);
|
||||
g_assert (NMP_OBJECT_IS_VALID (new));
|
||||
g_assert (nmp_object_is_alive (new));
|
||||
g_assert (nmp_object_id_equal (data->obj_clone, new));
|
||||
g_assert (nmp_object_equal (data->obj_clone, new));
|
||||
break;
|
||||
case NMP_CACHE_OPS_UPDATED:
|
||||
g_assert (NMP_OBJECT_IS_VALID (old));
|
||||
g_assert (NMP_OBJECT_IS_VALID (new));
|
||||
g_assert (nmp_object_is_alive (old));
|
||||
g_assert (nmp_object_is_alive (new));
|
||||
g_assert (nmp_object_id_equal (data->obj_clone, new));
|
||||
g_assert (nmp_object_id_equal (data->obj_clone, old));
|
||||
g_assert (nmp_object_id_equal (old, new));
|
||||
g_assert (nmp_object_equal (data->obj_clone, new));
|
||||
g_assert (!nmp_object_equal (data->obj_clone, old));
|
||||
g_assert (!nmp_object_equal (old, new));
|
||||
break;
|
||||
case NMP_CACHE_OPS_REMOVED:
|
||||
g_assert (!new);
|
||||
g_assert (NMP_OBJECT_IS_VALID (old));
|
||||
g_assert (nmp_object_is_alive (old));
|
||||
g_assert (nmp_object_id_equal (data->obj_clone, old));
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
data->was_visible = old ? nmp_object_is_visible (old) : FALSE;
|
||||
data->new_clone = new ? nmp_object_clone (new, FALSE) : NULL;
|
||||
data->called = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
_nmp_cache_update_netlink (NMPCache *cache, NMPObject *obj, NMPObject **out_obj, gboolean *out_was_visible, NMPCacheOpsType expected_ops_type)
|
||||
{
|
||||
NMPCacheOpsType ops_type;
|
||||
NMPObject *obj2;
|
||||
gboolean was_visible;
|
||||
auto_nmp_obj NMPObject *obj_clone = nmp_object_clone (obj, FALSE);
|
||||
auto_nmp_obj NMPObject *new_clone = NULL;
|
||||
const NMPObject *obj_old;
|
||||
_NMPCacheUpdateData data = {
|
||||
.cache = cache,
|
||||
.expected_ops_type = expected_ops_type,
|
||||
.obj_clone = obj_clone,
|
||||
};
|
||||
|
||||
obj_old = nmp_cache_lookup_link (cache, obj->object.ifindex);
|
||||
if (obj_old && obj_old->_link.udev.device)
|
||||
obj_clone->_link.udev.device = g_object_ref (obj_old->_link.udev.device);
|
||||
_nmp_object_fixup_link_udev_fields (obj_clone, nmp_cache_use_udev_get (cache));
|
||||
|
||||
g_assert (cache);
|
||||
g_assert (NMP_OBJECT_IS_VALID (obj));
|
||||
|
||||
ops_type = nmp_cache_update_netlink (cache, obj, &obj2, &was_visible, _nmp_cache_update_hook, &data);
|
||||
|
||||
new_clone = data.new_clone;
|
||||
|
||||
g_assert_cmpint (ops_type, ==, expected_ops_type);
|
||||
|
||||
if (ops_type != NMP_CACHE_OPS_UNCHANGED) {
|
||||
g_assert (NMP_OBJECT_IS_VALID (obj2));
|
||||
g_assert (data.called);
|
||||
g_assert_cmpint (data.was_visible, ==, was_visible);
|
||||
|
||||
if (ops_type == NMP_CACHE_OPS_REMOVED)
|
||||
g_assert (!data.new_clone);
|
||||
else {
|
||||
g_assert (data.new_clone);
|
||||
g_assert (nmp_object_equal (obj2, data.new_clone));
|
||||
}
|
||||
} else {
|
||||
g_assert (!data.called);
|
||||
g_assert (!obj2 || was_visible == nmp_object_is_visible (obj2));
|
||||
}
|
||||
|
||||
g_assert (!obj2 || nmp_object_id_equal (obj, obj2));
|
||||
if (ops_type != NMP_CACHE_OPS_REMOVED && obj2)
|
||||
g_assert (nmp_object_equal (obj, obj2));
|
||||
|
||||
if (out_obj)
|
||||
*out_obj = obj2;
|
||||
else
|
||||
nmp_object_unref (obj2);
|
||||
if (out_was_visible)
|
||||
*out_was_visible = was_visible;
|
||||
}
|
||||
|
||||
static const NMPlatformLink pl_link_2 = {
|
||||
.ifindex = 2,
|
||||
.name = "eth0",
|
||||
.type = NM_LINK_TYPE_ETHERNET,
|
||||
};
|
||||
|
||||
static const NMPlatformLink pl_link_3 = {
|
||||
.ifindex = 3,
|
||||
.name = "wlan0",
|
||||
.type = NM_LINK_TYPE_WIFI,
|
||||
};
|
||||
|
||||
static void
|
||||
test_cache_link ()
|
||||
{
|
||||
NMPCache *cache;
|
||||
NMPObject *obj1, *obj2;
|
||||
NMPObject objs1;
|
||||
gboolean was_visible;
|
||||
NMPCacheId cache_id_storage;
|
||||
GUdevDevice *udev_device_2 = g_list_nth_data (global.udev_devices, 0);
|
||||
GUdevDevice *udev_device_3 = g_list_nth_data (global.udev_devices, 0);
|
||||
NMPCacheOpsType ops_type;
|
||||
|
||||
cache = nmp_cache_new ();
|
||||
|
||||
nmp_cache_use_udev_set (cache, g_rand_int_range (nmtst_get_rand (), 0, 2));
|
||||
|
||||
/* if we have a link, and don't set is_in_netlink, adding it has no effect. */
|
||||
obj1 = nmp_object_new (OBJECT_TYPE_LINK, (NMPlatformObject *) &pl_link_2);
|
||||
g_assert (NMP_OBJECT_UP_CAST (&obj1->object) == obj1);
|
||||
g_assert (!nmp_object_is_alive (obj1));
|
||||
_nmp_cache_update_netlink (cache, obj1, &obj2, &was_visible, NMP_CACHE_OPS_UNCHANGED);
|
||||
ASSERT_nmp_cache_is_consistent (cache);
|
||||
g_assert (!obj2);
|
||||
g_assert (!was_visible);
|
||||
g_assert (!nmp_cache_lookup_obj (cache, obj1));
|
||||
g_assert (!nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_2.ifindex)));
|
||||
nmp_object_unref (obj1);
|
||||
|
||||
/* Only when setting @is_in_netlink the link is added. */
|
||||
obj1 = nmp_object_new (OBJECT_TYPE_LINK, (NMPlatformObject *) &pl_link_2);
|
||||
obj1->_link.netlink.is_in_netlink = TRUE;
|
||||
g_assert (nmp_object_is_alive (obj1));
|
||||
_nmp_cache_update_netlink (cache, obj1, &obj2, &was_visible, NMP_CACHE_OPS_ADDED);
|
||||
ASSERT_nmp_cache_is_consistent (cache);
|
||||
g_assert (nmp_object_equal (obj1, obj2));
|
||||
g_assert (!was_visible);
|
||||
g_assert (nmp_cache_lookup_obj (cache, obj1) == obj2);
|
||||
g_assert (nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_2.ifindex)) == obj2);
|
||||
g_assert (nmp_object_is_visible (obj2));
|
||||
_assert_cache_multi_lookup_contains (cache, nmp_cache_id_init_links (&cache_id_storage, TRUE), obj2, TRUE);
|
||||
_assert_cache_multi_lookup_contains (cache, nmp_cache_id_init_links (&cache_id_storage, FALSE), obj2, TRUE);
|
||||
nmp_object_unref (obj1);
|
||||
nmp_object_unref (obj2);
|
||||
|
||||
/* updating the same link with identical value, has no effect. */
|
||||
obj1 = nmp_object_new (OBJECT_TYPE_LINK, (NMPlatformObject *) &pl_link_2);
|
||||
obj1->_link.netlink.is_in_netlink = TRUE;
|
||||
g_assert (nmp_object_is_alive (obj1));
|
||||
_nmp_cache_update_netlink (cache, obj1, &obj2, &was_visible, NMP_CACHE_OPS_UNCHANGED);
|
||||
ASSERT_nmp_cache_is_consistent (cache);
|
||||
g_assert (obj2 != obj1);
|
||||
g_assert (nmp_object_equal (obj1, obj2));
|
||||
g_assert (was_visible);
|
||||
g_assert (nmp_cache_lookup_obj (cache, obj1) == obj2);
|
||||
g_assert (nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_2.ifindex)) == obj2);
|
||||
nmp_object_unref (obj1);
|
||||
nmp_object_unref (obj2);
|
||||
|
||||
/* remove the link from netlink */
|
||||
obj1 = nmp_object_new (OBJECT_TYPE_LINK, (NMPlatformObject *) &pl_link_2);
|
||||
g_assert (!nmp_object_is_alive (obj1));
|
||||
_nmp_cache_update_netlink (cache, obj1, &obj2, &was_visible, NMP_CACHE_OPS_REMOVED);
|
||||
ASSERT_nmp_cache_is_consistent (cache);
|
||||
g_assert (obj2 != obj1);
|
||||
g_assert (was_visible);
|
||||
g_assert (!nmp_cache_lookup_obj (cache, obj1));
|
||||
g_assert (!nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_2.ifindex)));
|
||||
nmp_object_unref (obj1);
|
||||
nmp_object_unref (obj2);
|
||||
|
||||
udev_device_2 = NULL;
|
||||
if (udev_device_2) {
|
||||
/* now add the link only with aspect UDEV. */
|
||||
ops_type = nmp_cache_update_link_udev (cache, pl_link_2.ifindex, udev_device_2, &obj2, &was_visible, NULL, NULL);
|
||||
ASSERT_nmp_cache_is_consistent (cache);
|
||||
g_assert_cmpint (ops_type, ==, NMP_CACHE_OPS_ADDED);
|
||||
g_assert (!was_visible);
|
||||
g_assert (nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_2.ifindex)) == obj2);
|
||||
g_assert (!nmp_object_is_visible (obj2));
|
||||
_assert_cache_multi_lookup_contains (cache, nmp_cache_id_init_links (&cache_id_storage, TRUE), obj2, FALSE);
|
||||
_assert_cache_multi_lookup_contains (cache, nmp_cache_id_init_links (&cache_id_storage, FALSE), obj2, TRUE);
|
||||
nmp_object_unref (obj2);
|
||||
}
|
||||
|
||||
/* add it in netlink too. */
|
||||
obj1 = nmp_object_new (OBJECT_TYPE_LINK, (NMPlatformObject *) &pl_link_2);
|
||||
obj1->_link.netlink.is_in_netlink = TRUE;
|
||||
g_assert (nmp_object_is_alive (obj1));
|
||||
_nmp_cache_update_netlink (cache, obj1, &obj2, &was_visible, udev_device_2 ? NMP_CACHE_OPS_UPDATED : NMP_CACHE_OPS_ADDED);
|
||||
ASSERT_nmp_cache_is_consistent (cache);
|
||||
g_assert (nmp_object_equal (obj1, obj2));
|
||||
g_assert (!was_visible);
|
||||
g_assert (nmp_cache_lookup_obj (cache, obj1) == obj2);
|
||||
g_assert (nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_2.ifindex)) == obj2);
|
||||
g_assert (nmp_object_is_visible (obj2));
|
||||
_assert_cache_multi_lookup_contains (cache, nmp_cache_id_init_links (&cache_id_storage, TRUE), obj2, TRUE);
|
||||
_assert_cache_multi_lookup_contains (cache, nmp_cache_id_init_links (&cache_id_storage, FALSE), obj2, TRUE);
|
||||
nmp_object_unref (obj1);
|
||||
nmp_object_unref (obj2);
|
||||
|
||||
/* remove again from netlink. */
|
||||
obj1 = nmp_object_new (OBJECT_TYPE_LINK, (NMPlatformObject *) &pl_link_2);
|
||||
obj1->_link.netlink.is_in_netlink = FALSE;
|
||||
g_assert (!nmp_object_is_alive (obj1));
|
||||
_nmp_cache_update_netlink (cache, obj1, &obj2, &was_visible, udev_device_2 ? NMP_CACHE_OPS_UPDATED : NMP_CACHE_OPS_REMOVED);
|
||||
ASSERT_nmp_cache_is_consistent (cache);
|
||||
g_assert (obj2 != obj1);
|
||||
g_assert (was_visible);
|
||||
if (udev_device_2) {
|
||||
g_assert (nmp_cache_lookup_obj (cache, obj1) == obj2);
|
||||
g_assert (nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_2.ifindex)) == obj2);
|
||||
g_assert (!nmp_object_is_visible (obj2));
|
||||
_assert_cache_multi_lookup_contains (cache, nmp_cache_id_init_links (&cache_id_storage, TRUE), obj2, FALSE);
|
||||
_assert_cache_multi_lookup_contains (cache, nmp_cache_id_init_links (&cache_id_storage, FALSE), obj2, TRUE);
|
||||
} else {
|
||||
g_assert (nmp_cache_lookup_obj (cache, obj1) == NULL);
|
||||
g_assert (nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_2.ifindex)) == NULL);
|
||||
g_assert (nmp_object_is_visible (obj2));
|
||||
}
|
||||
nmp_object_unref (obj1);
|
||||
nmp_object_unref (obj2);
|
||||
|
||||
/* now another link only with aspect UDEV. */
|
||||
if (udev_device_3) {
|
||||
/* now add the link only with aspect UDEV. */
|
||||
ops_type = nmp_cache_update_link_udev (cache, pl_link_3.ifindex, udev_device_3, &obj2, &was_visible, NULL, NULL);
|
||||
g_assert_cmpint (ops_type, ==, NMP_CACHE_OPS_ADDED);
|
||||
ASSERT_nmp_cache_is_consistent (cache);
|
||||
g_assert (NMP_OBJECT_IS_VALID (obj2));
|
||||
g_assert (!was_visible);
|
||||
g_assert (!nmp_object_is_visible (obj2));
|
||||
g_assert (nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_3.ifindex)) == obj2);
|
||||
_assert_cache_multi_lookup_contains (cache, nmp_cache_id_init_links (&cache_id_storage, TRUE), obj2, FALSE);
|
||||
_assert_cache_multi_lookup_contains (cache, nmp_cache_id_init_links (&cache_id_storage, FALSE), obj2, TRUE);
|
||||
g_assert_cmpint (obj2->_link.netlink.is_in_netlink, ==, FALSE);
|
||||
g_assert_cmpint (obj2->link.initialized, ==, FALSE);
|
||||
nmp_object_unref (obj2);
|
||||
|
||||
/* add it in netlink too. */
|
||||
obj1 = nmp_object_new (OBJECT_TYPE_LINK, (NMPlatformObject *) &pl_link_3);
|
||||
obj1->_link.netlink.is_in_netlink = TRUE;
|
||||
g_assert (nmp_object_is_alive (obj1));
|
||||
_nmp_cache_update_netlink (cache, obj1, &obj2, &was_visible, NMP_CACHE_OPS_UPDATED);
|
||||
ASSERT_nmp_cache_is_consistent (cache);
|
||||
g_assert (obj2 != obj1);
|
||||
g_assert (nmp_object_equal (obj1, obj2));
|
||||
g_assert (!was_visible);
|
||||
g_assert (nmp_cache_lookup_obj (cache, obj1) == obj2);
|
||||
g_assert (nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_3.ifindex)) == obj2);
|
||||
g_assert (nmp_object_is_visible (obj2));
|
||||
_assert_cache_multi_lookup_contains (cache, nmp_cache_id_init_links (&cache_id_storage, TRUE), obj2, TRUE);
|
||||
_assert_cache_multi_lookup_contains (cache, nmp_cache_id_init_links (&cache_id_storage, FALSE), obj2, TRUE);
|
||||
g_assert_cmpint (obj2->_link.netlink.is_in_netlink, ==, TRUE);
|
||||
g_assert_cmpint (obj2->link.initialized, ==, TRUE);
|
||||
nmp_object_unref (obj1);
|
||||
nmp_object_unref (obj2);
|
||||
|
||||
/* remove UDEV. */
|
||||
ops_type = nmp_cache_update_link_udev (cache, pl_link_3.ifindex, NULL, &obj2, &was_visible, NULL, NULL);
|
||||
g_assert_cmpint (ops_type, ==, NMP_CACHE_OPS_UPDATED);
|
||||
ASSERT_nmp_cache_is_consistent (cache);
|
||||
g_assert (was_visible);
|
||||
g_assert (nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_3.ifindex)) == obj2);
|
||||
g_assert (nmp_object_is_visible (obj2));
|
||||
_assert_cache_multi_lookup_contains (cache, nmp_cache_id_init_links (&cache_id_storage, TRUE), obj2, TRUE);
|
||||
_assert_cache_multi_lookup_contains (cache, nmp_cache_id_init_links (&cache_id_storage, FALSE), obj2, TRUE);
|
||||
g_assert_cmpint (obj2->_link.netlink.is_in_netlink, ==, TRUE);
|
||||
g_assert_cmpint (obj2->link.initialized, ==, !nmp_cache_use_udev_get (cache));
|
||||
nmp_object_unref (obj2);
|
||||
}
|
||||
|
||||
nmp_cache_free (cache);
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
|
||||
NMTST_DEFINE ();
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
int result;
|
||||
gs_unref_object GUdevClient *udev_client = NULL;
|
||||
|
||||
nmtst_init_assert_logging (&argc, &argv, "INFO", "DEFAULT");
|
||||
|
||||
udev_client = g_udev_client_new ((const char *[]) { "net", NULL });
|
||||
{
|
||||
gs_unref_object GUdevEnumerator *udev_enumerator = g_udev_enumerator_new (udev_client);
|
||||
|
||||
g_udev_enumerator_add_match_subsystem (udev_enumerator, "net");
|
||||
|
||||
/* Demand that the device is initialized (udev rules ran,
|
||||
* device has a stable name now) in case udev is running
|
||||
* (not in a container). */
|
||||
if (access ("/sys", W_OK) == 0)
|
||||
g_udev_enumerator_add_match_is_initialized (udev_enumerator);
|
||||
|
||||
global.udev_devices = g_udev_enumerator_execute (udev_enumerator);
|
||||
}
|
||||
|
||||
g_test_add_func ("/nmp-object/cache_link", test_cache_link);
|
||||
|
||||
result = g_test_run ();
|
||||
|
||||
while (global.udev_devices) {
|
||||
g_object_unref (global.udev_devices->data);
|
||||
global.udev_devices = g_list_remove (global.udev_devices, global.udev_devices->data);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
#include "config.h"
|
||||
|
||||
#include <linux/rtnetlink.h>
|
||||
|
||||
#include "test-common.h"
|
||||
#include "nm-test-utils.h"
|
||||
#include "NetworkManagerUtils.h"
|
||||
|
|
@ -64,7 +66,6 @@ test_ip4_route_metric0 (void)
|
|||
|
||||
/* add the first route */
|
||||
g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, network, plen, INADDR_ANY, 0, metric, mss));
|
||||
no_error ();
|
||||
accept_signal (route_added);
|
||||
|
||||
assert_ip4_route_exists (FALSE, DEVICE_NAME, network, plen, 0);
|
||||
|
|
@ -72,7 +73,6 @@ test_ip4_route_metric0 (void)
|
|||
|
||||
/* Deleting route with metric 0 does nothing */
|
||||
g_assert (nm_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, plen, 0));
|
||||
no_error ();
|
||||
ensure_no_signal (route_removed);
|
||||
|
||||
assert_ip4_route_exists (FALSE, DEVICE_NAME, network, plen, 0);
|
||||
|
|
@ -80,7 +80,6 @@ test_ip4_route_metric0 (void)
|
|||
|
||||
/* add the second route */
|
||||
g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, network, plen, INADDR_ANY, 0, 0, mss));
|
||||
no_error ();
|
||||
accept_signal (route_added);
|
||||
|
||||
assert_ip4_route_exists (TRUE, DEVICE_NAME, network, plen, 0);
|
||||
|
|
@ -88,7 +87,6 @@ test_ip4_route_metric0 (void)
|
|||
|
||||
/* Delete route with metric 0 */
|
||||
g_assert (nm_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, plen, 0));
|
||||
no_error ();
|
||||
accept_signal (route_removed);
|
||||
|
||||
assert_ip4_route_exists (FALSE, DEVICE_NAME, network, plen, 0);
|
||||
|
|
@ -96,7 +94,6 @@ test_ip4_route_metric0 (void)
|
|||
|
||||
/* Delete route with metric 0 again (we expect nothing to happen) */
|
||||
g_assert (nm_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, plen, 0));
|
||||
no_error ();
|
||||
ensure_no_signal (route_removed);
|
||||
|
||||
assert_ip4_route_exists (FALSE, DEVICE_NAME, network, plen, 0);
|
||||
|
|
@ -104,7 +101,6 @@ test_ip4_route_metric0 (void)
|
|||
|
||||
/* Delete the other route */
|
||||
g_assert (nm_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, plen, metric));
|
||||
no_error ();
|
||||
accept_signal (route_removed);
|
||||
|
||||
assert_ip4_route_exists (FALSE, DEVICE_NAME, network, plen, 0);
|
||||
|
|
@ -136,36 +132,27 @@ test_ip4_route (void)
|
|||
|
||||
/* Add route to gateway */
|
||||
g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, gateway, 32, INADDR_ANY, 0, metric, mss));
|
||||
no_error ();
|
||||
accept_signal (route_added);
|
||||
|
||||
/* Add route */
|
||||
assert_ip4_route_exists (FALSE, DEVICE_NAME, network, plen, metric);
|
||||
no_error ();
|
||||
g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, network, plen, gateway, 0, metric, mss));
|
||||
no_error ();
|
||||
assert_ip4_route_exists (TRUE, DEVICE_NAME, network, plen, metric);
|
||||
no_error ();
|
||||
accept_signal (route_added);
|
||||
|
||||
/* Add route again */
|
||||
g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, network, plen, gateway, 0, metric, mss));
|
||||
no_error ();
|
||||
accept_signal (route_changed);
|
||||
accept_signals (route_changed, 0, 1);
|
||||
|
||||
/* Add default route */
|
||||
assert_ip4_route_exists (FALSE, DEVICE_NAME, 0, 0, metric);
|
||||
no_error ();
|
||||
g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, 0, 0, gateway, 0, metric, mss));
|
||||
no_error ();
|
||||
assert_ip4_route_exists (TRUE, DEVICE_NAME, 0, 0, metric);
|
||||
no_error ();
|
||||
accept_signal (route_added);
|
||||
|
||||
/* Add default route again */
|
||||
g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, 0, 0, gateway, 0, metric, mss));
|
||||
no_error ();
|
||||
accept_signal (route_changed);
|
||||
accept_signals (route_changed, 0, 1);
|
||||
|
||||
/* Test route listing */
|
||||
routes = nm_platform_ip4_route_get_all (NM_PLATFORM_GET, ifindex, NM_PLATFORM_GET_ROUTE_MODE_ALL);
|
||||
|
|
@ -177,6 +164,7 @@ test_ip4_route (void)
|
|||
rts[0].gateway = INADDR_ANY;
|
||||
rts[0].metric = metric;
|
||||
rts[0].mss = mss;
|
||||
rts[0].scope_inv = nm_platform_route_scope_inv (RT_SCOPE_LINK);
|
||||
rts[1].source = NM_IP_CONFIG_SOURCE_USER;
|
||||
rts[1].network = network;
|
||||
rts[1].plen = plen;
|
||||
|
|
@ -184,6 +172,7 @@ test_ip4_route (void)
|
|||
rts[1].gateway = gateway;
|
||||
rts[1].metric = metric;
|
||||
rts[1].mss = mss;
|
||||
rts[1].scope_inv = nm_platform_route_scope_inv (RT_SCOPE_UNIVERSE);
|
||||
rts[2].source = NM_IP_CONFIG_SOURCE_USER;
|
||||
rts[2].network = 0;
|
||||
rts[2].plen = 0;
|
||||
|
|
@ -191,20 +180,18 @@ test_ip4_route (void)
|
|||
rts[2].gateway = gateway;
|
||||
rts[2].metric = metric;
|
||||
rts[2].mss = mss;
|
||||
rts[2].scope_inv = nm_platform_route_scope_inv (RT_SCOPE_UNIVERSE);
|
||||
g_assert_cmpint (routes->len, ==, 3);
|
||||
g_assert (!memcmp (routes->data, rts, sizeof (rts)));
|
||||
nmtst_platform_ip4_routes_equal ((NMPlatformIP4Route *) routes->data, rts, routes->len, TRUE);
|
||||
g_array_unref (routes);
|
||||
|
||||
/* Remove route */
|
||||
g_assert (nm_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, plen, metric));
|
||||
no_error ();
|
||||
assert_ip4_route_exists (FALSE, DEVICE_NAME, network, plen, metric);
|
||||
accept_signal (route_removed);
|
||||
|
||||
/* Remove route again */
|
||||
g_assert (nm_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, plen, metric));
|
||||
no_error ();
|
||||
|
||||
free_signal (route_added);
|
||||
free_signal (route_changed);
|
||||
|
|
@ -232,36 +219,27 @@ test_ip6_route (void)
|
|||
|
||||
/* Add route to gateway */
|
||||
g_assert (nm_platform_ip6_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, gateway, 128, in6addr_any, metric, mss));
|
||||
no_error ();
|
||||
accept_signal (route_added);
|
||||
|
||||
/* Add route */
|
||||
g_assert (!nm_platform_ip6_route_exists (NM_PLATFORM_GET, ifindex, network, plen, metric));
|
||||
no_error ();
|
||||
g_assert (nm_platform_ip6_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, network, plen, gateway, metric, mss));
|
||||
no_error ();
|
||||
g_assert (nm_platform_ip6_route_exists (NM_PLATFORM_GET, ifindex, network, plen, metric));
|
||||
no_error ();
|
||||
accept_signal (route_added);
|
||||
|
||||
/* Add route again */
|
||||
g_assert (nm_platform_ip6_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, network, plen, gateway, metric, mss));
|
||||
no_error ();
|
||||
accept_signal (route_changed);
|
||||
accept_signals (route_changed, 0, 1);
|
||||
|
||||
/* Add default route */
|
||||
g_assert (!nm_platform_ip6_route_exists (NM_PLATFORM_GET, ifindex, in6addr_any, 0, metric));
|
||||
no_error ();
|
||||
g_assert (nm_platform_ip6_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, in6addr_any, 0, gateway, metric, mss));
|
||||
no_error ();
|
||||
g_assert (nm_platform_ip6_route_exists (NM_PLATFORM_GET, ifindex, in6addr_any, 0, metric));
|
||||
no_error ();
|
||||
accept_signal (route_added);
|
||||
|
||||
/* Add default route again */
|
||||
g_assert (nm_platform_ip6_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, in6addr_any, 0, gateway, metric, mss));
|
||||
no_error ();
|
||||
accept_signal (route_changed);
|
||||
accept_signals (route_changed, 0, 1);
|
||||
|
||||
/* Test route listing */
|
||||
routes = nm_platform_ip6_route_get_all (NM_PLATFORM_GET, ifindex, NM_PLATFORM_GET_ROUTE_MODE_ALL);
|
||||
|
|
@ -288,19 +266,16 @@ test_ip6_route (void)
|
|||
rts[2].metric = nm_utils_ip6_route_metric_normalize (metric);
|
||||
rts[2].mss = mss;
|
||||
g_assert_cmpint (routes->len, ==, 3);
|
||||
g_assert (!memcmp (routes->data, rts, sizeof (rts)));
|
||||
nmtst_platform_ip6_routes_equal ((NMPlatformIP6Route *) routes->data, rts, routes->len, TRUE);
|
||||
g_array_unref (routes);
|
||||
|
||||
/* Remove route */
|
||||
g_assert (nm_platform_ip6_route_delete (NM_PLATFORM_GET, ifindex, network, plen, metric));
|
||||
no_error ();
|
||||
g_assert (!nm_platform_ip6_route_exists (NM_PLATFORM_GET, ifindex, network, plen, metric));
|
||||
accept_signal (route_removed);
|
||||
|
||||
/* Remove route again */
|
||||
g_assert (nm_platform_ip6_route_delete (NM_PLATFORM_GET, ifindex, network, plen, metric));
|
||||
no_error ();
|
||||
|
||||
free_signal (route_added);
|
||||
free_signal (route_changed);
|
||||
|
|
@ -320,11 +295,11 @@ setup_tests (void)
|
|||
|
||||
nm_platform_link_delete (NM_PLATFORM_GET, nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME));
|
||||
g_assert (!nm_platform_link_exists (NM_PLATFORM_GET, DEVICE_NAME));
|
||||
g_assert (nm_platform_dummy_add (NM_PLATFORM_GET, DEVICE_NAME, NULL));
|
||||
g_assert (nm_platform_dummy_add (NM_PLATFORM_GET, DEVICE_NAME, NULL) == NM_PLATFORM_ERROR_SUCCESS);
|
||||
accept_signal (link_added);
|
||||
free_signal (link_added);
|
||||
|
||||
g_assert (nm_platform_link_set_up (NM_PLATFORM_GET, nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME)));
|
||||
g_assert (nm_platform_link_set_up (NM_PLATFORM_GET, nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME), NULL));
|
||||
|
||||
g_test_add_func ("/route/ip4", test_ip4_route);
|
||||
g_test_add_func ("/route/ip6", test_ip6_route);
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
#include "NetworkManagerUtils.h"
|
||||
#include "nm-logging.h"
|
||||
#include "nm-multi-index.h"
|
||||
|
||||
#include "nm-test-utils.h"
|
||||
|
||||
|
|
@ -494,6 +495,362 @@ test_nm_ethernet_address_is_valid (void)
|
|||
|
||||
/*******************************************/
|
||||
|
||||
typedef struct {
|
||||
union {
|
||||
NMMultiIndexId id_base;
|
||||
guint bucket;
|
||||
};
|
||||
} NMMultiIndexIdTest;
|
||||
|
||||
typedef struct {
|
||||
guint64 buckets;
|
||||
gpointer ptr_value;
|
||||
} NMMultiIndexTestValue;
|
||||
|
||||
static gboolean
|
||||
_mi_value_bucket_has (const NMMultiIndexTestValue *value, guint bucket)
|
||||
{
|
||||
g_assert (value);
|
||||
g_assert (bucket < 64);
|
||||
|
||||
return (value->buckets & (((guint64) 0x01) << bucket)) != 0;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_mi_value_bucket_set (NMMultiIndexTestValue *value, guint bucket)
|
||||
{
|
||||
g_assert (value);
|
||||
g_assert (bucket < 64);
|
||||
|
||||
if (_mi_value_bucket_has (value, bucket))
|
||||
return FALSE;
|
||||
|
||||
value->buckets |= (((guint64) 0x01) << bucket);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_mi_value_bucket_unset (NMMultiIndexTestValue *value, guint bucket)
|
||||
{
|
||||
g_assert (value);
|
||||
g_assert (bucket < 64);
|
||||
|
||||
if (!_mi_value_bucket_has (value, bucket))
|
||||
return FALSE;
|
||||
|
||||
value->buckets &= ~(((guint64) 0x01) << bucket);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static guint
|
||||
_mi_idx_hash (const NMMultiIndexIdTest *id)
|
||||
{
|
||||
g_assert (id && id->bucket < 64);
|
||||
return id->bucket;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_mi_idx_equal (const NMMultiIndexIdTest *a, const NMMultiIndexIdTest *b)
|
||||
{
|
||||
g_assert (a && a->bucket < 64);
|
||||
g_assert (b && b->bucket < 64);
|
||||
|
||||
return a->bucket == b->bucket;
|
||||
}
|
||||
|
||||
static NMMultiIndexIdTest *
|
||||
_mi_idx_clone (const NMMultiIndexIdTest *id)
|
||||
{
|
||||
NMMultiIndexIdTest *n;
|
||||
|
||||
g_assert (id && id->bucket < 64);
|
||||
|
||||
n = g_new0 (NMMultiIndexIdTest, 1);
|
||||
n->bucket = id->bucket;
|
||||
return n;
|
||||
}
|
||||
|
||||
static void
|
||||
_mi_idx_destroy (NMMultiIndexIdTest *id)
|
||||
{
|
||||
g_assert (id && id->bucket < 64);
|
||||
g_free (id);
|
||||
}
|
||||
|
||||
static NMMultiIndexTestValue *
|
||||
_mi_create_array (guint num_values)
|
||||
{
|
||||
NMMultiIndexTestValue *array = g_new0 (NMMultiIndexTestValue, num_values);
|
||||
guint i;
|
||||
|
||||
g_assert (num_values > 0);
|
||||
|
||||
for (i = 0; i < num_values; i++) {
|
||||
array[i].buckets = 0;
|
||||
array[i].ptr_value = GUINT_TO_POINTER (i + 1);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
guint num_values;
|
||||
guint num_buckets;
|
||||
NMMultiIndexTestValue *array;
|
||||
int test_idx;
|
||||
} NMMultiIndexAssertData;
|
||||
|
||||
static gboolean
|
||||
_mi_assert_index_equals_array_cb (const NMMultiIndexIdTest *id, void *const* values, guint len, NMMultiIndexAssertData *data)
|
||||
{
|
||||
guint i;
|
||||
gboolean has_test_idx = FALSE;
|
||||
|
||||
g_assert (id && id->bucket < 64);
|
||||
g_assert (data);
|
||||
g_assert (values);
|
||||
g_assert (len > 0);
|
||||
g_assert (values[len] == NULL);
|
||||
g_assert (data->test_idx >= -1 || data->test_idx < data->num_buckets);
|
||||
|
||||
g_assert (id->bucket < data->num_buckets);
|
||||
|
||||
for (i = 0; i < data->num_values; i++)
|
||||
g_assert (!_mi_value_bucket_has (&data->array[i], id->bucket));
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
guint vi = GPOINTER_TO_UINT (values[i]);
|
||||
|
||||
g_assert (vi >= 1);
|
||||
g_assert (vi <= data->num_values);
|
||||
vi--;
|
||||
if (data->test_idx == vi)
|
||||
has_test_idx = TRUE;
|
||||
g_assert (data->array[vi].ptr_value == values[i]);
|
||||
if (!_mi_value_bucket_set (&data->array[vi], id->bucket))
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
g_assert ((data->test_idx == -1 && !has_test_idx) || has_test_idx);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
_mi_assert_index_equals_array (guint num_values, guint num_buckets, int test_idx, const NMMultiIndexTestValue *array, const NMMultiIndex *index)
|
||||
{
|
||||
NMMultiIndexAssertData data = {
|
||||
.num_values = num_values,
|
||||
.num_buckets = num_buckets,
|
||||
.test_idx = test_idx,
|
||||
};
|
||||
NMMultiIndexIter iter;
|
||||
const NMMultiIndexIdTest *id;
|
||||
void *const* values;
|
||||
guint len;
|
||||
NMMultiIndexTestValue *v;
|
||||
|
||||
data.array = _mi_create_array (num_values);
|
||||
v = test_idx >= 0 ? data.array[test_idx].ptr_value : NULL;
|
||||
nm_multi_index_foreach (index, v, (NMMultiIndexFuncForeach) _mi_assert_index_equals_array_cb, &data);
|
||||
if (test_idx >= 0)
|
||||
g_assert (memcmp (&data.array[test_idx], &array[test_idx], sizeof (NMMultiIndexTestValue)) == 0);
|
||||
else
|
||||
g_assert (memcmp (data.array, array, sizeof (NMMultiIndexTestValue) * num_values) == 0);
|
||||
g_free (data.array);
|
||||
|
||||
|
||||
data.array = _mi_create_array (num_values);
|
||||
v = test_idx >= 0 ? data.array[test_idx].ptr_value : NULL;
|
||||
nm_multi_index_iter_init (&iter, index, v);
|
||||
while (nm_multi_index_iter_next (&iter, (gpointer) &id, &values, &len))
|
||||
_mi_assert_index_equals_array_cb (id, values, len, &data);
|
||||
if (test_idx >= 0)
|
||||
g_assert (memcmp (&data.array[test_idx], &array[test_idx], sizeof (NMMultiIndexTestValue)) == 0);
|
||||
else
|
||||
g_assert (memcmp (data.array, array, sizeof (NMMultiIndexTestValue) * num_values) == 0);
|
||||
g_free (data.array);
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
MI_OP_ADD,
|
||||
MI_OP_REMOVE,
|
||||
MI_OP_MOVE,
|
||||
} NMMultiIndexOperation;
|
||||
|
||||
static void
|
||||
_mi_rebucket (GRand *rand, guint num_values, guint num_buckets, NMMultiIndexOperation op, guint bucket, guint bucket_old, guint array_idx, NMMultiIndexTestValue *array, NMMultiIndex *index)
|
||||
{
|
||||
NMMultiIndexTestValue *v;
|
||||
NMMultiIndexIdTest id, id_old;
|
||||
const NMMultiIndexIdTest *id_reverse;
|
||||
guint64 buckets_old;
|
||||
guint i;
|
||||
gboolean had_bucket, had_bucket_old;
|
||||
|
||||
g_assert (array_idx < num_values);
|
||||
g_assert (bucket < (int) num_buckets);
|
||||
|
||||
v = &array[array_idx];
|
||||
|
||||
buckets_old = v->buckets;
|
||||
if (op == MI_OP_MOVE)
|
||||
had_bucket_old = _mi_value_bucket_has (v, bucket_old);
|
||||
else
|
||||
had_bucket_old = FALSE;
|
||||
had_bucket = _mi_value_bucket_has (v, bucket);
|
||||
|
||||
switch (op) {
|
||||
|
||||
case MI_OP_ADD:
|
||||
_mi_value_bucket_set (v, bucket);
|
||||
id.bucket = bucket;
|
||||
if (nm_multi_index_add (index, &id.id_base, v->ptr_value))
|
||||
g_assert (!had_bucket);
|
||||
else
|
||||
g_assert (had_bucket);
|
||||
break;
|
||||
|
||||
case MI_OP_REMOVE:
|
||||
_mi_value_bucket_unset (v, bucket);
|
||||
id.bucket = bucket;
|
||||
if (nm_multi_index_remove (index, &id.id_base, v->ptr_value))
|
||||
g_assert (had_bucket);
|
||||
else
|
||||
g_assert (!had_bucket);
|
||||
break;
|
||||
|
||||
case MI_OP_MOVE:
|
||||
|
||||
_mi_value_bucket_unset (v, bucket_old);
|
||||
_mi_value_bucket_set (v, bucket);
|
||||
|
||||
id.bucket = bucket;
|
||||
id_old.bucket = bucket_old;
|
||||
|
||||
if (nm_multi_index_move (index, &id_old.id_base, &id.id_base, v->ptr_value)) {
|
||||
if (bucket == bucket_old)
|
||||
g_assert (had_bucket_old && had_bucket);
|
||||
else
|
||||
g_assert (had_bucket_old && !had_bucket);
|
||||
} else {
|
||||
if (bucket == bucket_old)
|
||||
g_assert (!had_bucket_old && !had_bucket);
|
||||
else
|
||||
g_assert (!had_bucket_old || had_bucket);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
#if 0
|
||||
g_print (">>> rebucket: idx=%3u, op=%3s, bucket=%3i%c -> %3i%c, buckets=%08llx -> %08llx %s\n", array_idx,
|
||||
op == MI_OP_ADD ? "ADD" : (op == MI_OP_REMOVE ? "REM" : "MOV"),
|
||||
bucket_old, had_bucket_old ? '*' : ' ',
|
||||
bucket, had_bucket ? '*' : ' ',
|
||||
(long long unsigned) buckets_old, (long long unsigned) v->buckets,
|
||||
buckets_old != v->buckets ? "(changed)" : "(unchanged)");
|
||||
#endif
|
||||
|
||||
id_reverse = (const NMMultiIndexIdTest *) nm_multi_index_lookup_first_by_value (index, v->ptr_value);
|
||||
if (id_reverse)
|
||||
g_assert (_mi_value_bucket_has (v, id_reverse->bucket));
|
||||
else
|
||||
g_assert (v->buckets == 0);
|
||||
|
||||
for (i = 0; i < 64; i++) {
|
||||
id.bucket = i;
|
||||
if (nm_multi_index_contains (index, &id.id_base, v->ptr_value))
|
||||
g_assert (_mi_value_bucket_has (v, i));
|
||||
else
|
||||
g_assert (!_mi_value_bucket_has (v, i));
|
||||
}
|
||||
|
||||
_mi_assert_index_equals_array (num_values, num_buckets, -1, array, index);
|
||||
_mi_assert_index_equals_array (num_values, num_buckets, array_idx, array, index);
|
||||
_mi_assert_index_equals_array (num_values, num_buckets, g_rand_int_range (rand, 0, num_values), array, index);
|
||||
}
|
||||
|
||||
static void
|
||||
_mi_test_run (guint num_values, guint num_buckets)
|
||||
{
|
||||
NMMultiIndex *index = nm_multi_index_new ((NMMultiIndexFuncHash) _mi_idx_hash,
|
||||
(NMMultiIndexFuncEqual) _mi_idx_equal,
|
||||
(NMMultiIndexFuncClone) _mi_idx_clone,
|
||||
(NMMultiIndexFuncDestroy) _mi_idx_destroy);
|
||||
gs_free NMMultiIndexTestValue *array = _mi_create_array (num_values);
|
||||
GRand *rand = nmtst_get_rand ();
|
||||
guint i, i_rd, i_idx, i_bucket;
|
||||
guint num_buckets_all = num_values * num_buckets;
|
||||
|
||||
g_assert (array[0].ptr_value == GUINT_TO_POINTER (1));
|
||||
|
||||
_mi_assert_index_equals_array (num_values, num_buckets, -1, array, index);
|
||||
|
||||
_mi_rebucket (rand, num_values, num_buckets, MI_OP_ADD, 0, 0, 0, array, index);
|
||||
_mi_rebucket (rand, num_values, num_buckets, MI_OP_REMOVE, 0, 0, 0, array, index);
|
||||
|
||||
if (num_buckets >= 3) {
|
||||
_mi_rebucket (rand, num_values, num_buckets, MI_OP_ADD, 0, 0, 0, array, index);
|
||||
_mi_rebucket (rand, num_values, num_buckets, MI_OP_MOVE, 2, 0, 0, array, index);
|
||||
_mi_rebucket (rand, num_values, num_buckets, MI_OP_REMOVE, 2, 0, 0, array, index);
|
||||
}
|
||||
|
||||
g_assert (nm_multi_index_get_num_groups (index) == 0);
|
||||
|
||||
/* randomly change the bucket of entries. */
|
||||
for (i = 0; i < 5 * num_values; i++) {
|
||||
guint array_idx = g_rand_int_range (rand, 0, num_values);
|
||||
guint bucket = g_rand_int_range (rand, 0, num_buckets);
|
||||
NMMultiIndexOperation op = g_rand_int_range (rand, 0, MI_OP_MOVE + 1);
|
||||
guint bucket_old = 0;
|
||||
|
||||
if (op == MI_OP_MOVE) {
|
||||
if ((g_rand_int (rand) % 2) && array[array_idx].buckets != 0) {
|
||||
guint64 b;
|
||||
|
||||
/* choose the highest (existing) bucket. */
|
||||
bucket_old = 0;
|
||||
for (b = array[array_idx].buckets; b; b >>= 1)
|
||||
bucket_old++;
|
||||
} else {
|
||||
/* choose a random bucket (even if the item is currently not in that bucket). */
|
||||
bucket_old = g_rand_int_range (rand, 0, num_buckets);
|
||||
}
|
||||
}
|
||||
|
||||
_mi_rebucket (rand, num_values, num_buckets, op, bucket, bucket_old, array_idx, array, index);
|
||||
}
|
||||
|
||||
/* remove all elements from all buckets */
|
||||
i_rd = g_rand_int (rand);
|
||||
for (i = 0; i < num_buckets_all; i++) {
|
||||
i_rd = (i_rd + 101) % num_buckets_all;
|
||||
i_idx = i_rd / num_buckets;
|
||||
i_bucket = i_rd % num_buckets;
|
||||
|
||||
if (_mi_value_bucket_has (&array[i_idx], i_bucket))
|
||||
_mi_rebucket (rand, num_values, num_buckets, MI_OP_REMOVE, i_bucket, 0, i_idx, array, index);
|
||||
}
|
||||
|
||||
g_assert (nm_multi_index_get_num_groups (index) == 0);
|
||||
nm_multi_index_free (index);
|
||||
}
|
||||
|
||||
static void
|
||||
test_nm_multi_index (void)
|
||||
{
|
||||
guint i, j;
|
||||
|
||||
for (i = 1; i < 7; i++) {
|
||||
for (j = 1; j < 6; j++)
|
||||
_mi_test_run (i, j);
|
||||
}
|
||||
_mi_test_run (50, 3);
|
||||
_mi_test_run (50, 18);
|
||||
}
|
||||
|
||||
/*******************************************/
|
||||
|
||||
NMTST_DEFINE ();
|
||||
|
||||
int
|
||||
|
|
@ -505,6 +862,7 @@ main (int argc, char **argv)
|
|||
g_test_add_func ("/general/nm_utils_kill_child", test_nm_utils_kill_child);
|
||||
g_test_add_func ("/general/nm_utils_array_remove_at_indexes", test_nm_utils_array_remove_at_indexes);
|
||||
g_test_add_func ("/general/nm_ethernet_address_is_valid", test_nm_ethernet_address_is_valid);
|
||||
g_test_add_func ("/general/nm_multi_index", test_nm_multi_index);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
#include <glib.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
|
||||
#include "test-common.h"
|
||||
|
||||
|
|
@ -168,6 +169,7 @@ test_ip4 (test_fixture *fixture, gconstpointer user_data)
|
|||
.gateway = INADDR_ANY,
|
||||
.metric = 20,
|
||||
.mss = 1000,
|
||||
.scope_inv = nm_platform_route_scope_inv (RT_SCOPE_LINK),
|
||||
},
|
||||
{
|
||||
.source = NM_IP_CONFIG_SOURCE_USER,
|
||||
|
|
@ -177,6 +179,7 @@ test_ip4 (test_fixture *fixture, gconstpointer user_data)
|
|||
.gateway = nmtst_inet4_from_string ("6.6.6.1"),
|
||||
.metric = 21021,
|
||||
.mss = 0,
|
||||
.scope_inv = nm_platform_route_scope_inv (RT_SCOPE_UNIVERSE),
|
||||
},
|
||||
{
|
||||
.source = NM_IP_CONFIG_SOURCE_USER,
|
||||
|
|
@ -186,6 +189,7 @@ test_ip4 (test_fixture *fixture, gconstpointer user_data)
|
|||
.gateway = INADDR_ANY,
|
||||
.metric = 22,
|
||||
.mss = 0,
|
||||
.scope_inv = nm_platform_route_scope_inv (RT_SCOPE_LINK),
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -198,6 +202,7 @@ test_ip4 (test_fixture *fixture, gconstpointer user_data)
|
|||
.gateway = INADDR_ANY,
|
||||
.metric = 20,
|
||||
.mss = 0,
|
||||
.scope_inv = nm_platform_route_scope_inv (RT_SCOPE_LINK),
|
||||
},
|
||||
{
|
||||
.source = NM_IP_CONFIG_SOURCE_USER,
|
||||
|
|
@ -207,6 +212,7 @@ test_ip4 (test_fixture *fixture, gconstpointer user_data)
|
|||
.gateway = INADDR_ANY,
|
||||
.metric = 21,
|
||||
.mss = 0,
|
||||
.scope_inv = nm_platform_route_scope_inv (RT_SCOPE_LINK),
|
||||
},
|
||||
{
|
||||
.source = NM_IP_CONFIG_SOURCE_USER,
|
||||
|
|
@ -216,6 +222,7 @@ test_ip4 (test_fixture *fixture, gconstpointer user_data)
|
|||
.gateway = INADDR_ANY,
|
||||
.metric = 22,
|
||||
.mss = 0,
|
||||
.scope_inv = nm_platform_route_scope_inv (RT_SCOPE_LINK),
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -228,6 +235,7 @@ test_ip4 (test_fixture *fixture, gconstpointer user_data)
|
|||
.gateway = INADDR_ANY,
|
||||
.metric = 22,
|
||||
.mss = 0,
|
||||
.scope_inv = nm_platform_route_scope_inv (RT_SCOPE_LINK),
|
||||
},
|
||||
{
|
||||
.source = NM_IP_CONFIG_SOURCE_USER,
|
||||
|
|
@ -237,11 +245,12 @@ test_ip4 (test_fixture *fixture, gconstpointer user_data)
|
|||
.gateway = INADDR_ANY,
|
||||
.metric = 20,
|
||||
.mss = 0,
|
||||
.scope_inv = nm_platform_route_scope_inv (RT_SCOPE_LINK),
|
||||
},
|
||||
};
|
||||
|
||||
setup_dev0_ip4 (fixture->ifindex0, 1000, 21021);
|
||||
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, "*error adding 8.0.0.0/8 via 6.6.6.2 dev *");
|
||||
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, "*failure adding ip4-route '*: 8.0.0.0/8 22': *");
|
||||
setup_dev1_ip4 (fixture->ifindex1);
|
||||
g_test_assert_expected_messages ();
|
||||
|
||||
|
|
@ -253,7 +262,7 @@ test_ip4 (test_fixture *fixture, gconstpointer user_data)
|
|||
nmtst_platform_ip4_routes_equal ((NMPlatformIP4Route *) routes->data, state1, routes->len, TRUE);
|
||||
g_array_free (routes, TRUE);
|
||||
|
||||
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, "*error adding 8.0.0.0/8 via 6.6.6.2 dev *");
|
||||
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, "*failure adding ip4-route '*: 8.0.0.0/8 22': *");
|
||||
setup_dev1_ip4 (fixture->ifindex1);
|
||||
g_test_assert_expected_messages ();
|
||||
|
||||
|
|
@ -575,7 +584,7 @@ test_ip6 (test_fixture *fixture, gconstpointer user_data)
|
|||
};
|
||||
|
||||
setup_dev0_ip6 (fixture->ifindex0);
|
||||
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, "*error adding 2001:db8:d34d::/64 via 2001:db8:8086::2 dev *");
|
||||
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, "*failure adding ip6-route '*: 2001:db8:d34d::/64 20': *");
|
||||
setup_dev1_ip6 (fixture->ifindex1);
|
||||
g_test_assert_expected_messages ();
|
||||
|
||||
|
|
@ -589,7 +598,7 @@ test_ip6 (test_fixture *fixture, gconstpointer user_data)
|
|||
g_array_free (routes, TRUE);
|
||||
|
||||
|
||||
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, "*error adding 2001:db8:d34d::/64 via 2001:db8:8086::2 dev *");
|
||||
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, "*failure adding ip6-route '*: 2001:db8:d34d::/64 20': *");
|
||||
setup_dev1_ip6 (fixture->ifindex1);
|
||||
g_test_assert_expected_messages ();
|
||||
setup_dev0_ip6 (fixture->ifindex0);
|
||||
|
|
@ -639,11 +648,11 @@ fixture_setup (test_fixture *fixture, gconstpointer user_data)
|
|||
"nm-test-device0");
|
||||
nm_platform_link_delete (NM_PLATFORM_GET, nm_platform_link_get_ifindex (NM_PLATFORM_GET, "nm-test-device0"));
|
||||
g_assert (!nm_platform_link_exists (NM_PLATFORM_GET, "nm-test-device0"));
|
||||
g_assert (nm_platform_dummy_add (NM_PLATFORM_GET, "nm-test-device0", NULL));
|
||||
g_assert (nm_platform_dummy_add (NM_PLATFORM_GET, "nm-test-device0", NULL) == NM_PLATFORM_ERROR_SUCCESS);
|
||||
accept_signal (link_added);
|
||||
free_signal (link_added);
|
||||
fixture->ifindex0 = nm_platform_link_get_ifindex (NM_PLATFORM_GET, "nm-test-device0");
|
||||
g_assert (nm_platform_link_set_up (NM_PLATFORM_GET, fixture->ifindex0));
|
||||
g_assert (nm_platform_link_set_up (NM_PLATFORM_GET, fixture->ifindex0, NULL));
|
||||
|
||||
link_added = add_signal_ifname (NM_PLATFORM_SIGNAL_LINK_CHANGED,
|
||||
NM_PLATFORM_SIGNAL_ADDED,
|
||||
|
|
@ -651,11 +660,11 @@ fixture_setup (test_fixture *fixture, gconstpointer user_data)
|
|||
"nm-test-device1");
|
||||
nm_platform_link_delete (NM_PLATFORM_GET, nm_platform_link_get_ifindex (NM_PLATFORM_GET, "nm-test-device1"));
|
||||
g_assert (!nm_platform_link_exists (NM_PLATFORM_GET, "nm-test-device1"));
|
||||
g_assert (nm_platform_dummy_add (NM_PLATFORM_GET, "nm-test-device1", NULL));
|
||||
g_assert (nm_platform_dummy_add (NM_PLATFORM_GET, "nm-test-device1", NULL) == NM_PLATFORM_ERROR_SUCCESS);
|
||||
accept_signal (link_added);
|
||||
free_signal (link_added);
|
||||
fixture->ifindex1 = nm_platform_link_get_ifindex (NM_PLATFORM_GET, "nm-test-device1");
|
||||
g_assert (nm_platform_link_set_up (NM_PLATFORM_GET, fixture->ifindex1));
|
||||
g_assert (nm_platform_link_set_up (NM_PLATFORM_GET, fixture->ifindex1, NULL));
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
|
|
@ -921,7 +921,7 @@ nm_vpn_connection_apply_config (NMVpnConnection *connection)
|
|||
NMVpnConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (connection);
|
||||
|
||||
if (priv->ip_ifindex > 0) {
|
||||
nm_platform_link_set_up (NM_PLATFORM_GET, priv->ip_ifindex);
|
||||
nm_platform_link_set_up (NM_PLATFORM_GET, priv->ip_ifindex, NULL);
|
||||
|
||||
if (priv->ip4_config) {
|
||||
if (!nm_ip4_config_commit (priv->ip4_config, priv->ip_ifindex,
|
||||
|
|
|
|||
|
|
@ -417,24 +417,6 @@
|
|||
# libnl3
|
||||
###############################################################
|
||||
|
||||
{
|
||||
# fixed by https://github.com/thom311/libnl/commit/d65c32a7205e679c7fc13f0e4565b13e698ba906
|
||||
libnl_rtnl_link_set_type_01
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: definite
|
||||
fun:calloc
|
||||
fun:vlan_alloc
|
||||
fun:rtnl_link_set_type
|
||||
fun:link_msg_parser
|
||||
fun:__pickup_answer
|
||||
fun:nl_cb_call
|
||||
fun:recvmsgs
|
||||
fun:nl_recvmsgs_report
|
||||
fun:nl_recvmsgs
|
||||
fun:nl_pickup
|
||||
fun:rtnl_link_get_kernel
|
||||
...
|
||||
}
|
||||
{
|
||||
# fixed by https://github.com/thom311/libnl/commit/d65c32a7205e679c7fc13f0e4565b13e698ba906
|
||||
# Same issue as libnl_rtnl_link_set_type_01, but different backtrace by calling nl_msg_parse().
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue