mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-01-06 14:20:16 +01:00
platform: merge branch 'th/platform-netlink-events'
Add test cases for certain netlink peculiarities and fix our NMLinxPlatform implementation to handle them better.
This commit is contained in:
commit
7300e59c14
21 changed files with 535 additions and 1096 deletions
|
|
@ -69,6 +69,8 @@
|
|||
* If you set the level to DEBUG or TRACE, it also sets G_MESSAGES_DEBUG=all (unless
|
||||
* in assert-logging mode and unless G_MESSAGES_DEBUG is already defined).
|
||||
*
|
||||
* "TRACE", this is shorthand for "log-level=TRACE".
|
||||
*
|
||||
* "sudo-cmd=PATH": when running root tests as normal user, the test will execute
|
||||
* itself by invoking sudo at PATH.
|
||||
* For example
|
||||
|
|
@ -126,16 +128,26 @@ nmtst_assert_error (GError *error,
|
|||
}
|
||||
}
|
||||
|
||||
#define NMTST_BUSY_WAIT(max_wait_ms, condition, wait) \
|
||||
G_STMT_START { \
|
||||
#define NMTST_WAIT(max_wait_ms, wait) \
|
||||
({ \
|
||||
gboolean _not_expired = TRUE; \
|
||||
gint64 _nmtst_end, _nmtst_max_wait_us = (max_wait_ms) * 1000L; \
|
||||
\
|
||||
_nmtst_end = g_get_monotonic_time () + _nmtst_max_wait_us; \
|
||||
while (!(condition)) { \
|
||||
while (TRUE) { \
|
||||
{ wait }; \
|
||||
if (g_get_monotonic_time () > _nmtst_end) \
|
||||
g_assert_not_reached (); \
|
||||
if (g_get_monotonic_time () > _nmtst_end) { \
|
||||
_not_expired = FALSE; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
_not_expired; \
|
||||
})
|
||||
|
||||
#define NMTST_WAIT_ASSERT(max_wait_ms, wait) \
|
||||
G_STMT_START { \
|
||||
if (!(NMTST_WAIT (max_wait_ms, wait))) \
|
||||
g_assert_not_reached (); \
|
||||
} G_STMT_END
|
||||
|
||||
inline static void
|
||||
|
|
@ -322,6 +334,9 @@ __nmtst_init (int *argc, char ***argv, gboolean assert_logging, const char *log_
|
|||
} else if (!g_ascii_strncasecmp (debug, "log-level=", strlen ("log-level="))) {
|
||||
g_free (c_log_level);
|
||||
log_level = c_log_level = g_strdup (&debug[strlen ("log-level=")]);
|
||||
} else if (!g_ascii_strcasecmp (debug, "TRACE")) {
|
||||
g_free (c_log_level);
|
||||
log_level = c_log_level = g_strdup (debug);
|
||||
} else if (!g_ascii_strncasecmp (debug, "log-domains=", strlen ("log-domains="))) {
|
||||
g_free (c_log_domains);
|
||||
log_domains = c_log_domains = g_strdup (&debug[strlen ("log-domains=")]);
|
||||
|
|
|
|||
|
|
@ -292,7 +292,7 @@ error:
|
|||
}
|
||||
|
||||
static void
|
||||
link_changed_cb (NMPlatform *platform, NMPObjectType obj_type, int ifindex, NMPlatformLink *info, NMPlatformSignalChangeType change_type, NMPlatformReason reason, NMDeviceAdsl *self)
|
||||
link_changed_cb (NMPlatform *platform, NMPObjectType obj_type, int ifindex, NMPlatformLink *info, NMPlatformSignalChangeType change_type, NMDeviceAdsl *self)
|
||||
{
|
||||
if (change_type == NM_PLATFORM_SIGNAL_REMOVED) {
|
||||
NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (self);
|
||||
|
|
|
|||
|
|
@ -1580,7 +1580,6 @@ link_changed_cb (NMPlatform *platform,
|
|||
int ifindex,
|
||||
NMPlatformLink *info,
|
||||
NMPlatformSignalChangeType change_type,
|
||||
NMPlatformReason reason,
|
||||
NMDevice *self)
|
||||
{
|
||||
NMDevicePrivate *priv;
|
||||
|
|
@ -1590,12 +1589,6 @@ link_changed_cb (NMPlatform *platform,
|
|||
|
||||
priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
|
||||
/* We don't filter by 'reason' because we are interested in *all* link
|
||||
* changes. For example a call to nm_platform_link_set_up() may result
|
||||
* in an internal carrier change (i.e. we ask the kernel to set IFF_UP
|
||||
* and it results in also setting IFF_LOWER_UP.
|
||||
*/
|
||||
|
||||
if (ifindex == nm_device_get_ifindex (self)) {
|
||||
if (!priv->device_link_changed_id) {
|
||||
priv->device_link_changed_id = g_idle_add ((GSourceFunc) device_link_changed, self);
|
||||
|
|
@ -7932,7 +7925,6 @@ device_ipx_changed (NMPlatform *platform,
|
|||
int ifindex,
|
||||
gpointer platform_object,
|
||||
NMPlatformSignalChangeType change_type,
|
||||
NMPlatformReason reason,
|
||||
NMDevice *self)
|
||||
{
|
||||
NMDevicePrivate *priv;
|
||||
|
|
|
|||
|
|
@ -1359,7 +1359,6 @@ _platform_changed_cb (NMPlatform *platform,
|
|||
int ifindex,
|
||||
gpointer platform_object,
|
||||
NMPlatformSignalChangeType change_type,
|
||||
NMPlatformReason reason,
|
||||
NMDefaultRouteManager *self)
|
||||
{
|
||||
switch (obj_type) {
|
||||
|
|
|
|||
|
|
@ -332,7 +332,6 @@ ip6_address_changed (NMPlatform *platform,
|
|||
int iface,
|
||||
NMPlatformIP6Address *addr,
|
||||
NMPlatformSignalChangeType change_type,
|
||||
NMPlatformReason reason,
|
||||
NMRDisc *rdisc)
|
||||
{
|
||||
if ( (change_type == NM_PLATFORM_SIGNAL_CHANGED && addr->flags & IFA_F_DADFAILED)
|
||||
|
|
|
|||
|
|
@ -1965,7 +1965,6 @@ platform_link_cb (NMPlatform *platform,
|
|||
int ifindex,
|
||||
NMPlatformLink *plink,
|
||||
NMPlatformSignalChangeType change_type,
|
||||
NMPlatformReason reason,
|
||||
gpointer user_data)
|
||||
{
|
||||
PlatformLinkCbData *data;
|
||||
|
|
|
|||
|
|
@ -1009,7 +1009,6 @@ _ip4_device_routes_ip4_route_changed (NMPlatform *platform,
|
|||
int ifindex,
|
||||
const NMPlatformIP4Route *route,
|
||||
NMPlatformSignalChangeType change_type,
|
||||
NMPlatformReason reason,
|
||||
NMRouteManager *self)
|
||||
{
|
||||
NMRouteManagerPrivate *priv;
|
||||
|
|
|
|||
|
|
@ -308,7 +308,7 @@ link_add (NMPlatform *platform,
|
|||
g_array_append_val (priv->links, device);
|
||||
|
||||
if (device.link.ifindex) {
|
||||
g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_LINK_CHANGED, NMP_OBJECT_TYPE_LINK, device.link.ifindex, &device, NM_PLATFORM_SIGNAL_ADDED, NM_PLATFORM_REASON_INTERNAL);
|
||||
g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_LINK_CHANGED, NMP_OBJECT_TYPE_LINK, device.link.ifindex, &device, NM_PLATFORM_SIGNAL_ADDED);
|
||||
|
||||
link_changed (platform, &g_array_index (priv->links, NMFakePlatformLink, priv->links->len - 1), FALSE);
|
||||
}
|
||||
|
|
@ -360,7 +360,7 @@ link_delete (NMPlatform *platform, int ifindex)
|
|||
memset (route, 0, sizeof (*route));
|
||||
}
|
||||
|
||||
g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_LINK_CHANGED, NMP_OBJECT_TYPE_LINK, ifindex, &deleted_device, NM_PLATFORM_SIGNAL_REMOVED, NM_PLATFORM_REASON_INTERNAL);
|
||||
g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_LINK_CHANGED, NMP_OBJECT_TYPE_LINK, ifindex, &deleted_device, NM_PLATFORM_SIGNAL_REMOVED);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -378,7 +378,7 @@ link_changed (NMPlatform *platform, NMFakePlatformLink *device, gboolean raise_s
|
|||
int i;
|
||||
|
||||
if (raise_signal)
|
||||
g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_LINK_CHANGED, NMP_OBJECT_TYPE_LINK, device->link.ifindex, &device->link, NM_PLATFORM_SIGNAL_CHANGED, NM_PLATFORM_REASON_INTERNAL);
|
||||
g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_LINK_CHANGED, NMP_OBJECT_TYPE_LINK, device->link.ifindex, &device->link, NM_PLATFORM_SIGNAL_CHANGED);
|
||||
|
||||
if (device->link.ifindex && !IN6_IS_ADDR_UNSPECIFIED (&device->ip6_lladdr)) {
|
||||
if (device->link.connected)
|
||||
|
|
@ -925,12 +925,12 @@ ip4_address_add (NMPlatform *platform,
|
|||
|
||||
memcpy (item, &address, sizeof (address));
|
||||
if (changed)
|
||||
g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED, NMP_OBJECT_TYPE_IP4_ADDRESS, ifindex, &address, NM_PLATFORM_SIGNAL_CHANGED, NM_PLATFORM_REASON_INTERNAL);
|
||||
g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED, NMP_OBJECT_TYPE_IP4_ADDRESS, ifindex, &address, NM_PLATFORM_SIGNAL_CHANGED);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
g_array_append_val (priv->ip4_addresses, address);
|
||||
g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED, NMP_OBJECT_TYPE_IP4_ADDRESS, ifindex, &address, NM_PLATFORM_SIGNAL_ADDED, NM_PLATFORM_REASON_INTERNAL);
|
||||
g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED, NMP_OBJECT_TYPE_IP4_ADDRESS, ifindex, &address, NM_PLATFORM_SIGNAL_ADDED);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -971,12 +971,12 @@ ip6_address_add (NMPlatform *platform,
|
|||
|
||||
memcpy (item, &address, sizeof (address));
|
||||
if (changed)
|
||||
g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED, NMP_OBJECT_TYPE_IP6_ADDRESS, ifindex, &address, NM_PLATFORM_SIGNAL_CHANGED, NM_PLATFORM_REASON_INTERNAL);
|
||||
g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED, NMP_OBJECT_TYPE_IP6_ADDRESS, ifindex, &address, NM_PLATFORM_SIGNAL_CHANGED);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
g_array_append_val (priv->ip6_addresses, address);
|
||||
g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED, NMP_OBJECT_TYPE_IP6_ADDRESS, ifindex, &address, NM_PLATFORM_SIGNAL_ADDED, NM_PLATFORM_REASON_INTERNAL);
|
||||
g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED, NMP_OBJECT_TYPE_IP6_ADDRESS, ifindex, &address, NM_PLATFORM_SIGNAL_ADDED);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -998,7 +998,7 @@ ip4_address_delete (NMPlatform *platform, int ifindex, in_addr_t addr, int plen,
|
|||
|
||||
memcpy (&deleted_address, address, sizeof (deleted_address));
|
||||
memset (address, 0, sizeof (*address));
|
||||
g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED, NMP_OBJECT_TYPE_IP4_ADDRESS, ifindex, &deleted_address, NM_PLATFORM_SIGNAL_REMOVED, NM_PLATFORM_REASON_INTERNAL);
|
||||
g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED, NMP_OBJECT_TYPE_IP4_ADDRESS, ifindex, &deleted_address, NM_PLATFORM_SIGNAL_REMOVED);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
|
@ -1022,7 +1022,7 @@ ip6_address_delete (NMPlatform *platform, int ifindex, struct in6_addr addr, int
|
|||
|
||||
memcpy (&deleted_address, address, sizeof (deleted_address));
|
||||
memset (address, 0, sizeof (*address));
|
||||
g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED, NMP_OBJECT_TYPE_IP6_ADDRESS, ifindex, &deleted_address, NM_PLATFORM_SIGNAL_REMOVED, NM_PLATFORM_REASON_INTERNAL);
|
||||
g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED, NMP_OBJECT_TYPE_IP6_ADDRESS, ifindex, &deleted_address, NM_PLATFORM_SIGNAL_REMOVED);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
|
@ -1146,7 +1146,7 @@ ip4_route_delete (NMPlatform *platform, int ifindex, in_addr_t network, int plen
|
|||
|
||||
memcpy (&deleted_route, route, sizeof (deleted_route));
|
||||
g_array_remove_index (priv->ip4_routes, i);
|
||||
g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, NMP_OBJECT_TYPE_IP4_ROUTE, ifindex, &deleted_route, NM_PLATFORM_SIGNAL_REMOVED, NM_PLATFORM_REASON_INTERNAL);
|
||||
g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, NMP_OBJECT_TYPE_IP4_ROUTE, ifindex, &deleted_route, NM_PLATFORM_SIGNAL_REMOVED);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
|
@ -1172,7 +1172,7 @@ ip6_route_delete (NMPlatform *platform, int ifindex, struct in6_addr network, in
|
|||
|
||||
memcpy (&deleted_route, route, sizeof (deleted_route));
|
||||
g_array_remove_index (priv->ip6_routes, i);
|
||||
g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, NMP_OBJECT_TYPE_IP6_ROUTE, ifindex, &deleted_route, NM_PLATFORM_SIGNAL_REMOVED, NM_PLATFORM_REASON_INTERNAL);
|
||||
g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, NMP_OBJECT_TYPE_IP6_ROUTE, ifindex, &deleted_route, NM_PLATFORM_SIGNAL_REMOVED);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
|
@ -1235,12 +1235,12 @@ ip4_route_add (NMPlatform *platform, int ifindex, NMIPConfigSource source,
|
|||
}
|
||||
|
||||
memcpy (item, &route, sizeof (route));
|
||||
g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, NMP_OBJECT_TYPE_IP4_ROUTE, ifindex, &route, NM_PLATFORM_SIGNAL_CHANGED, NM_PLATFORM_REASON_INTERNAL);
|
||||
g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, NMP_OBJECT_TYPE_IP4_ROUTE, ifindex, &route, NM_PLATFORM_SIGNAL_CHANGED);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
g_array_append_val (priv->ip4_routes, route);
|
||||
g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, NMP_OBJECT_TYPE_IP4_ROUTE, ifindex, &route, NM_PLATFORM_SIGNAL_ADDED, NM_PLATFORM_REASON_INTERNAL);
|
||||
g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, NMP_OBJECT_TYPE_IP4_ROUTE, ifindex, &route, NM_PLATFORM_SIGNAL_ADDED);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -1302,12 +1302,12 @@ ip6_route_add (NMPlatform *platform, int ifindex, NMIPConfigSource source,
|
|||
}
|
||||
|
||||
memcpy (item, &route, sizeof (route));
|
||||
g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, NMP_OBJECT_TYPE_IP6_ROUTE, ifindex, &route, NM_PLATFORM_SIGNAL_CHANGED, NM_PLATFORM_REASON_INTERNAL);
|
||||
g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, NMP_OBJECT_TYPE_IP6_ROUTE, ifindex, &route, NM_PLATFORM_SIGNAL_CHANGED);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
g_array_append_val (priv->ip6_routes, route);
|
||||
g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, NMP_OBJECT_TYPE_IP6_ROUTE, ifindex, &route, NM_PLATFORM_SIGNAL_ADDED, NM_PLATFORM_REASON_INTERNAL);
|
||||
g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, NMP_OBJECT_TYPE_IP6_ROUTE, ifindex, &route, NM_PLATFORM_SIGNAL_ADDED);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -149,7 +149,6 @@ static void do_request_link (NMPlatform *platform, int ifindex, const char *name
|
|||
static void do_request_all (NMPlatform *platform, DelayedActionType action_type, gboolean handle_delayed_action);
|
||||
static void cache_pre_hook (NMPCache *cache, const NMPObject *old, const NMPObject *new, NMPCacheOpsType ops_type, gpointer user_data);
|
||||
static gboolean event_handler_read_netlink_all (NMPlatform *platform, gboolean wait_for_acks);
|
||||
static NMPCacheOpsType cache_remove_netlink (NMPlatform *platform, const NMPObject *obj_id, NMPObject **out_obj_cache, gboolean *out_was_visible, NMPlatformReason reason);
|
||||
|
||||
/******************************************************************
|
||||
* Support IFLA_INET6_ADDR_GEN_MODE
|
||||
|
|
@ -2200,7 +2199,6 @@ struct _NMLinuxPlatformPrivate {
|
|||
} delayed_action;
|
||||
|
||||
GHashTable *prune_candidates;
|
||||
GHashTable *delayed_deletion;
|
||||
|
||||
GHashTable *wifi_data;
|
||||
};
|
||||
|
|
@ -2257,7 +2255,7 @@ process_events (NMPlatform *platform)
|
|||
/******************************************************************/
|
||||
|
||||
static void
|
||||
do_emit_signal (NMPlatform *platform, const NMPObject *obj, NMPCacheOpsType cache_op, gboolean was_visible, NMPlatformReason reason)
|
||||
do_emit_signal (NMPlatform *platform, const NMPObject *obj, NMPCacheOpsType cache_op, gboolean was_visible)
|
||||
{
|
||||
gboolean is_visible;
|
||||
NMPObject obj_clone;
|
||||
|
|
@ -2304,16 +2302,21 @@ do_emit_signal (NMPlatform *platform, const NMPObject *obj, NMPCacheOpsType cach
|
|||
|
||||
klass = NMP_OBJECT_GET_CLASS (obj);
|
||||
|
||||
_LOGt ("emit signal %s %s: %s (%ld)",
|
||||
_LOGt ("emit signal %s %s: %s",
|
||||
klass->signal_type,
|
||||
nm_platform_signal_change_type_to_string ((NMPlatformSignalChangeType) cache_op),
|
||||
nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0),
|
||||
(long) reason);
|
||||
nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0));
|
||||
|
||||
/* don't expose @obj directly, but clone the public fields. A signal handler might
|
||||
* call back into NMPlatform which could invalidate (or modify) @obj. */
|
||||
memcpy (&obj_clone.object, &obj->object, klass->sizeof_public);
|
||||
g_signal_emit_by_name (platform, klass->signal_type, klass->obj_type, obj_clone.object.ifindex, &obj_clone.object, (NMPlatformSignalChangeType) cache_op, reason);
|
||||
g_signal_emit (platform,
|
||||
_nm_platform_signal_id_get (klass->signal_type_id),
|
||||
0,
|
||||
klass->obj_type,
|
||||
obj_clone.object.ifindex,
|
||||
&obj_clone.object,
|
||||
(NMPlatformSignalChangeType) cache_op);
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
|
|
@ -2373,7 +2376,7 @@ delayed_action_handle_MASTER_CONNECTED (NMPlatform *platform, int master_ifindex
|
|||
NMPCacheOpsType cache_op;
|
||||
|
||||
cache_op = nmp_cache_update_link_master_connected (priv->cache, master_ifindex, &obj_cache, &was_visible, cache_pre_hook, platform);
|
||||
do_emit_signal (platform, obj_cache, cache_op, was_visible, NM_PLATFORM_REASON_INTERNAL);
|
||||
do_emit_signal (platform, obj_cache, cache_op, was_visible);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -2490,33 +2493,6 @@ delayed_action_handle_idle (gpointer user_data)
|
|||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
delayed_action_clear_REFRESH_LINK (NMPlatform *platform, int ifindex)
|
||||
{
|
||||
NMLinuxPlatformPrivate *priv;
|
||||
gssize idx;
|
||||
gpointer user_data;
|
||||
|
||||
if (ifindex <= 0)
|
||||
return;
|
||||
|
||||
priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
|
||||
if (!NM_FLAGS_HAS (priv->delayed_action.flags, DELAYED_ACTION_TYPE_REFRESH_LINK))
|
||||
return;
|
||||
|
||||
user_data = GINT_TO_POINTER (ifindex);
|
||||
|
||||
idx = _nm_utils_ptrarray_find_first (priv->delayed_action.list_refresh_link->pdata, priv->delayed_action.list_refresh_link->len, user_data);
|
||||
if (idx < 0)
|
||||
return;
|
||||
|
||||
_LOGt_delayed_action (DELAYED_ACTION_TYPE_REFRESH_LINK, user_data, "clear");
|
||||
|
||||
g_ptr_array_remove_index_fast (priv->delayed_action.list_refresh_link, idx);
|
||||
if (priv->delayed_action.list_refresh_link->len == 0)
|
||||
priv->delayed_action.flags &= ~DELAYED_ACTION_TYPE_REFRESH_LINK;
|
||||
}
|
||||
|
||||
static void
|
||||
delayed_action_schedule (NMPlatform *platform, DelayedActionType action_type, gpointer user_data)
|
||||
{
|
||||
|
|
@ -2619,45 +2595,12 @@ cache_prune_candidates_prune (NMPlatform *platform)
|
|||
|
||||
_LOGt ("cache-prune: prune %s", nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_ALL, NULL, 0));
|
||||
cache_op = nmp_cache_remove (priv->cache, obj, TRUE, &obj_cache, &was_visible, cache_pre_hook, platform);
|
||||
do_emit_signal (platform, obj_cache, cache_op, was_visible, NM_PLATFORM_REASON_INTERNAL);
|
||||
do_emit_signal (platform, obj_cache, cache_op, was_visible);
|
||||
}
|
||||
|
||||
g_hash_table_unref (prune_candidates);
|
||||
}
|
||||
|
||||
static void
|
||||
cache_delayed_deletion_prune (NMPlatform *platform)
|
||||
{
|
||||
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
|
||||
GPtrArray *prune_list = NULL;
|
||||
GHashTableIter iter;
|
||||
guint i;
|
||||
NMPObject *obj;
|
||||
|
||||
if (g_hash_table_size (priv->delayed_deletion) == 0)
|
||||
return;
|
||||
|
||||
g_hash_table_iter_init (&iter, priv->delayed_deletion);
|
||||
while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &obj)) {
|
||||
if (obj) {
|
||||
if (!prune_list)
|
||||
prune_list = g_ptr_array_new_full (g_hash_table_size (priv->delayed_deletion), (GDestroyNotify) nmp_object_unref);
|
||||
g_ptr_array_add (prune_list, nmp_object_ref (obj));
|
||||
}
|
||||
}
|
||||
|
||||
g_hash_table_remove_all (priv->delayed_deletion);
|
||||
|
||||
if (prune_list) {
|
||||
for (i = 0; i < prune_list->len; i++) {
|
||||
obj = prune_list->pdata[i];
|
||||
_LOGt ("delayed-deletion: delete %s", nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_ID, NULL, 0));
|
||||
cache_remove_netlink (platform, obj, NULL, NULL, NM_PLATFORM_REASON_EXTERNAL);
|
||||
}
|
||||
g_ptr_array_unref (prune_list);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cache_pre_hook (NMPCache *cache, const NMPObject *old, const NMPObject *new, NMPCacheOpsType ops_type, gpointer user_data)
|
||||
{
|
||||
|
|
@ -2738,7 +2681,8 @@ cache_pre_hook (NMPCache *cache, const NMPObject *old, const NMPObject *new, NMP
|
|||
|
||||
/* removal of a link could be caused by moving the link to another netns.
|
||||
* In this case, we potentially have to update other links that have this link as parent.
|
||||
* Currently, kernel misses to sent us a notification in this case (rh #1262908). */
|
||||
* Currently, kernel misses to sent us a notification in this case
|
||||
* (https://bugzilla.redhat.com/show_bug.cgi?id=1262908). */
|
||||
|
||||
if ( ops_type == NMP_CACHE_OPS_REMOVED
|
||||
&& old /* <-- nonsensical, make coverity happy */
|
||||
|
|
@ -2778,6 +2722,40 @@ cache_pre_hook (NMPCache *cache, const NMPObject *old, const NMPObject *new, NMP
|
|||
NULL);
|
||||
}
|
||||
}
|
||||
if ( NM_IN_SET (ops_type, NMP_CACHE_OPS_ADDED, NMP_CACHE_OPS_UPDATED)
|
||||
&& (new && new->_link.netlink.is_in_netlink)
|
||||
&& (!old || !old->_link.netlink.is_in_netlink))
|
||||
{
|
||||
if (!new->_link.netlink.lnk) {
|
||||
/* certain link-types also come with a IFLA_INFO_DATA/lnk_data. It may happen that
|
||||
* kernel didn't send this notification, thus when we first learn about a link
|
||||
* that lacks an lnk_data we re-request it again.
|
||||
*
|
||||
* For example https://bugzilla.redhat.com/show_bug.cgi?id=1284001 */
|
||||
switch (new->link.type) {
|
||||
case NM_LINK_TYPE_GRE:
|
||||
case NM_LINK_TYPE_INFINIBAND:
|
||||
case NM_LINK_TYPE_MACVLAN:
|
||||
case NM_LINK_TYPE_VLAN:
|
||||
case NM_LINK_TYPE_VXLAN:
|
||||
delayed_action_schedule (platform,
|
||||
DELAYED_ACTION_TYPE_REFRESH_LINK,
|
||||
GINT_TO_POINTER (new->link.ifindex));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( new->link.type == NM_LINK_TYPE_VETH
|
||||
&& new->link.parent == 0) {
|
||||
/* the initial notification when adding a veth pair can lack the parent/IFLA_LINK
|
||||
* (https://bugzilla.redhat.com/show_bug.cgi?id=1285827).
|
||||
* Request it again. */
|
||||
delayed_action_schedule (platform,
|
||||
DELAYED_ACTION_TYPE_REFRESH_LINK,
|
||||
GINT_TO_POINTER (new->link.ifindex));
|
||||
}
|
||||
}
|
||||
{
|
||||
/* on enslave/release, we also refresh the master. */
|
||||
int ifindex1 = 0, ifindex2 = 0;
|
||||
|
|
@ -2797,7 +2775,22 @@ cache_pre_hook (NMPCache *cache, const NMPObject *old, const NMPObject *new, NMP
|
|||
if (ifindex2 > 0 && ifindex1 != ifindex2)
|
||||
delayed_action_schedule (platform, DELAYED_ACTION_TYPE_REFRESH_LINK, GINT_TO_POINTER (ifindex2));
|
||||
}
|
||||
|
||||
}
|
||||
{
|
||||
if ( ( (ops_type == NMP_CACHE_OPS_REMOVED)
|
||||
|| ( (ops_type == NMP_CACHE_OPS_UPDATED)
|
||||
&& new
|
||||
&& !new->_link.netlink.is_in_netlink))
|
||||
&& old
|
||||
&& old->_link.netlink.is_in_netlink
|
||||
&& old->link.master) {
|
||||
/* sometimes we receive a wrong RTM_DELLINK message when unslaving
|
||||
* a device. Refetch the link again to check whether the device
|
||||
* is really gone.
|
||||
*
|
||||
* https://bugzilla.redhat.com/show_bug.cgi?id=1285719#c2 */
|
||||
delayed_action_schedule (platform, DELAYED_ACTION_TYPE_REFRESH_LINK, GINT_TO_POINTER (old->link.ifindex));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NMP_OBJECT_TYPE_IP4_ADDRESS:
|
||||
|
|
@ -2819,7 +2812,7 @@ cache_pre_hook (NMPCache *cache, const NMPObject *old, const NMPObject *new, NMP
|
|||
}
|
||||
|
||||
static NMPCacheOpsType
|
||||
cache_remove_netlink (NMPlatform *platform, const NMPObject *obj_id, NMPObject **out_obj_cache, gboolean *out_was_visible, NMPlatformReason reason)
|
||||
cache_remove_netlink (NMPlatform *platform, const NMPObject *obj_id, NMPObject **out_obj_cache, gboolean *out_was_visible)
|
||||
{
|
||||
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
|
||||
NMPObject *obj_cache;
|
||||
|
|
@ -2827,7 +2820,7 @@ cache_remove_netlink (NMPlatform *platform, const NMPObject *obj_id, NMPObject *
|
|||
NMPCacheOpsType cache_op;
|
||||
|
||||
cache_op = nmp_cache_remove_netlink (priv->cache, obj_id, &obj_cache, &was_visible, cache_pre_hook, platform);
|
||||
do_emit_signal (platform, obj_cache, cache_op, was_visible, NM_PLATFORM_REASON_INTERNAL);
|
||||
do_emit_signal (platform, obj_cache, cache_op, was_visible);
|
||||
|
||||
if (out_obj_cache)
|
||||
*out_obj_cache = obj_cache;
|
||||
|
|
@ -2840,7 +2833,7 @@ cache_remove_netlink (NMPlatform *platform, const NMPObject *obj_id, NMPObject *
|
|||
}
|
||||
|
||||
static NMPCacheOpsType
|
||||
cache_update_netlink (NMPlatform *platform, NMPObject *obj, NMPObject **out_obj_cache, gboolean *out_was_visible, NMPlatformReason reason)
|
||||
cache_update_netlink (NMPlatform *platform, NMPObject *obj, NMPObject **out_obj_cache, gboolean *out_was_visible)
|
||||
{
|
||||
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
|
||||
NMPObject *obj_cache;
|
||||
|
|
@ -2851,7 +2844,7 @@ cache_update_netlink (NMPlatform *platform, NMPObject *obj, NMPObject **out_obj_
|
|||
* at once. */
|
||||
|
||||
cache_op = nmp_cache_update_netlink (priv->cache, obj, &obj_cache, &was_visible, cache_pre_hook, platform);
|
||||
do_emit_signal (platform, obj_cache, cache_op, was_visible, reason);
|
||||
do_emit_signal (platform, obj_cache, cache_op, was_visible);
|
||||
|
||||
if (out_obj_cache)
|
||||
*out_obj_cache = obj_cache;
|
||||
|
|
@ -2891,13 +2884,8 @@ do_request_link (NMPlatform *platform, int ifindex, const char *name, gboolean h
|
|||
_LOGD ("do-request-link: %d %s", ifindex, name ? name : "");
|
||||
|
||||
if (ifindex > 0) {
|
||||
NMPObject *obj;
|
||||
|
||||
cache_prune_candidates_record_one (platform,
|
||||
(NMPObject *) nmp_cache_lookup_link (priv->cache, ifindex));
|
||||
obj = nmp_object_new_link (ifindex);
|
||||
_LOGt ("delayed-deletion: protect object %s", nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_ID, NULL, 0));
|
||||
g_hash_table_insert (priv->delayed_deletion, obj, NULL);
|
||||
}
|
||||
|
||||
event_handler_read_netlink_all (platform, FALSE);
|
||||
|
|
@ -2918,7 +2906,6 @@ do_request_link (NMPlatform *platform, int ifindex, const char *name, gboolean h
|
|||
|
||||
event_handler_read_netlink_all (platform, TRUE);
|
||||
|
||||
cache_delayed_deletion_prune (platform);
|
||||
cache_prune_candidates_prune (platform);
|
||||
|
||||
if (handle_delayed_action)
|
||||
|
|
@ -3076,34 +3063,15 @@ event_notification (struct nl_msg *msg, gpointer user_data)
|
|||
switch (msghdr->nlmsg_type) {
|
||||
|
||||
case RTM_NEWLINK:
|
||||
if (NMP_OBJECT_GET_TYPE (obj) == NMP_OBJECT_TYPE_LINK) {
|
||||
if (g_hash_table_lookup (priv->delayed_deletion, obj) != NULL) {
|
||||
/* the object is scheduled for delayed deletion. Replace that object
|
||||
* by clearing the value from priv->delayed_deletion. */
|
||||
_LOGt ("delayed-deletion: clear delayed deletion of protected object %s", nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_ID, NULL, 0));
|
||||
g_hash_table_insert (priv->delayed_deletion, nmp_object_ref (obj), NULL);
|
||||
}
|
||||
delayed_action_clear_REFRESH_LINK (platform, obj->link.ifindex);
|
||||
}
|
||||
/* fall-through */
|
||||
case RTM_NEWADDR:
|
||||
case RTM_NEWROUTE:
|
||||
cache_update_netlink (platform, obj, &obj_cache, NULL, NM_PLATFORM_REASON_EXTERNAL);
|
||||
cache_update_netlink (platform, obj, &obj_cache, NULL);
|
||||
break;
|
||||
|
||||
case RTM_DELLINK:
|
||||
if ( NMP_OBJECT_GET_TYPE (obj) == NMP_OBJECT_TYPE_LINK
|
||||
&& g_hash_table_contains (priv->delayed_deletion, obj)) {
|
||||
/* We sometimes receive spurious RTM_DELLINK events. In this case, we want to delay
|
||||
* the deletion of the object until later. */
|
||||
_LOGt ("delayed-deletion: delay deletion of protected object %s", nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_ID, NULL, 0));
|
||||
g_hash_table_insert (priv->delayed_deletion, nmp_object_ref (obj), nmp_object_ref (obj));
|
||||
break;
|
||||
}
|
||||
/* fall-through */
|
||||
case RTM_DELADDR:
|
||||
case RTM_DELROUTE:
|
||||
cache_remove_netlink (platform, obj, &obj_cache, NULL, NM_PLATFORM_REASON_EXTERNAL);
|
||||
cache_remove_netlink (platform, obj, &obj_cache, NULL);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
@ -5201,7 +5169,7 @@ cache_update_link_udev (NMPlatform *platform, int ifindex, GUdevDevice *udev_dev
|
|||
NMPCacheOpsType cache_op;
|
||||
|
||||
cache_op = nmp_cache_update_link_udev (priv->cache, ifindex, udev_device, &obj_cache, &was_visible, cache_pre_hook, platform);
|
||||
do_emit_signal (platform, obj_cache, cache_op, was_visible, NM_PLATFORM_REASON_INTERNAL);
|
||||
do_emit_signal (platform, obj_cache, cache_op, was_visible);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -5304,10 +5272,6 @@ nm_linux_platform_init (NMLinuxPlatform *self)
|
|||
|
||||
self->priv = priv;
|
||||
|
||||
priv->delayed_deletion = g_hash_table_new_full ((GHashFunc) nmp_object_id_hash,
|
||||
(GEqualFunc) nmp_object_id_equal,
|
||||
(GDestroyNotify) nmp_object_unref,
|
||||
(GDestroyNotify) nmp_object_unref);
|
||||
priv->cache = nmp_cache_new ();
|
||||
priv->delayed_action.list_master_connected = g_ptr_array_new ();
|
||||
priv->delayed_action.list_refresh_link = g_ptr_array_new ();
|
||||
|
|
@ -5410,7 +5374,6 @@ dispose (GObject *object)
|
|||
nm_clear_g_source (&priv->delayed_action.idle_id);
|
||||
|
||||
g_clear_pointer (&priv->prune_candidates, g_hash_table_unref);
|
||||
g_clear_pointer (&priv->delayed_deletion, g_hash_table_unref);
|
||||
|
||||
G_OBJECT_CLASS (nm_linux_platform_parent_class)->dispose (object);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,17 +77,7 @@ G_STATIC_ASSERT (G_STRUCT_OFFSET (NMPlatformIPRoute, network_ptr) == G_STRUCT_OF
|
|||
|
||||
G_DEFINE_TYPE (NMPlatform, nm_platform, G_TYPE_OBJECT)
|
||||
|
||||
/* NMPlatform signals */
|
||||
enum {
|
||||
SIGNAL_LINK_CHANGED,
|
||||
SIGNAL_IP4_ADDRESS_CHANGED,
|
||||
SIGNAL_IP6_ADDRESS_CHANGED,
|
||||
SIGNAL_IP4_ROUTE_CHANGED,
|
||||
SIGNAL_IP6_ROUTE_CHANGED,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL] = { 0 };
|
||||
static guint signals[_NM_PLATFORM_SIGNAL_ID_LAST] = { 0 };
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
|
|
@ -101,6 +91,18 @@ typedef struct {
|
|||
|
||||
/******************************************************************/
|
||||
|
||||
guint
|
||||
_nm_platform_signal_id_get (NMPlatformSignalIdType signal_type)
|
||||
{
|
||||
nm_assert ( signal_type > 0
|
||||
&& signal_type != NM_PLATFORM_SIGNAL_ID_NONE
|
||||
&& signal_type < _NM_PLATFORM_SIGNAL_ID_LAST);
|
||||
|
||||
return signals[signal_type];
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
|
||||
/* Singleton NMPlatform subclass instance and cached class object */
|
||||
NM_DEFINE_SINGLETON_INSTANCE (NMPlatform);
|
||||
|
||||
|
|
@ -3697,14 +3699,6 @@ nm_platform_init (NMPlatform *object)
|
|||
{
|
||||
}
|
||||
|
||||
#define SIGNAL(signal_id, method) signals[signal_id] = \
|
||||
g_signal_new_class_handler (NM_PLATFORM_ ## signal_id, \
|
||||
G_OBJECT_CLASS_TYPE (object_class), \
|
||||
G_SIGNAL_RUN_FIRST, \
|
||||
G_CALLBACK (method), \
|
||||
NULL, NULL, NULL, \
|
||||
G_TYPE_NONE, 5, NM_TYPE_POBJECT_TYPE, G_TYPE_INT, G_TYPE_POINTER, NM_TYPE_PLATFORM_SIGNAL_CHANGE_TYPE, NM_TYPE_PLATFORM_REASON);
|
||||
|
||||
static void
|
||||
nm_platform_class_init (NMPlatformClass *platform_class)
|
||||
{
|
||||
|
|
@ -3725,10 +3719,21 @@ nm_platform_class_init (NMPlatformClass *platform_class)
|
|||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
|
||||
#define SIGNAL(signal, signal_id, method) \
|
||||
G_STMT_START { \
|
||||
signals[signal] = \
|
||||
g_signal_new_class_handler (""signal_id"", \
|
||||
G_OBJECT_CLASS_TYPE (object_class), \
|
||||
G_SIGNAL_RUN_FIRST, \
|
||||
G_CALLBACK (method), \
|
||||
NULL, NULL, NULL, \
|
||||
G_TYPE_NONE, 4, NM_TYPE_POBJECT_TYPE, G_TYPE_INT, G_TYPE_POINTER, NM_TYPE_PLATFORM_SIGNAL_CHANGE_TYPE); \
|
||||
} G_STMT_END
|
||||
|
||||
/* Signals */
|
||||
SIGNAL (SIGNAL_LINK_CHANGED, log_link)
|
||||
SIGNAL (SIGNAL_IP4_ADDRESS_CHANGED, log_ip4_address)
|
||||
SIGNAL (SIGNAL_IP6_ADDRESS_CHANGED, log_ip6_address)
|
||||
SIGNAL (SIGNAL_IP4_ROUTE_CHANGED, log_ip4_route)
|
||||
SIGNAL (SIGNAL_IP6_ROUTE_CHANGED, log_ip6_route)
|
||||
SIGNAL (NM_PLATFORM_SIGNAL_ID_LINK, NM_PLATFORM_SIGNAL_LINK_CHANGED, log_link);
|
||||
SIGNAL (NM_PLATFORM_SIGNAL_ID_IP4_ADDRESS, NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED, log_ip4_address);
|
||||
SIGNAL (NM_PLATFORM_SIGNAL_ID_IP6_ADDRESS, NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED, log_ip6_address);
|
||||
SIGNAL (NM_PLATFORM_SIGNAL_ID_IP4_ROUTE, NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, log_ip4_route);
|
||||
SIGNAL (NM_PLATFORM_SIGNAL_ID_IP6_ROUTE, NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, log_ip6_route);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -83,19 +83,6 @@ typedef enum { /*< skip >*/
|
|||
NM_PLATFORM_ERROR_NO_FIRMWARE,
|
||||
} NMPlatformError;
|
||||
|
||||
typedef enum {
|
||||
NM_PLATFORM_REASON_NONE,
|
||||
/* Event was requested by NetworkManager. */
|
||||
NM_PLATFORM_REASON_INTERNAL,
|
||||
/* Event came from the kernel. */
|
||||
NM_PLATFORM_REASON_EXTERNAL,
|
||||
/* Event is a result of cache checking and cleanups. */
|
||||
NM_PLATFORM_REASON_CACHE_CHECK,
|
||||
|
||||
/* Internal reason to suppress announcing change events */
|
||||
_NM_PLATFORM_REASON_CACHE_CHECK_INTERNAL,
|
||||
} NMPlatformReason;
|
||||
|
||||
|
||||
typedef struct {
|
||||
union {
|
||||
|
|
@ -166,6 +153,18 @@ struct _NMPlatformLink {
|
|||
guint mtu;
|
||||
};
|
||||
|
||||
typedef enum { /*< skip >*/
|
||||
NM_PLATFORM_SIGNAL_ID_NONE,
|
||||
NM_PLATFORM_SIGNAL_ID_LINK,
|
||||
NM_PLATFORM_SIGNAL_ID_IP4_ADDRESS,
|
||||
NM_PLATFORM_SIGNAL_ID_IP6_ADDRESS,
|
||||
NM_PLATFORM_SIGNAL_ID_IP4_ROUTE,
|
||||
NM_PLATFORM_SIGNAL_ID_IP6_ROUTE,
|
||||
_NM_PLATFORM_SIGNAL_ID_LAST,
|
||||
} NMPlatformSignalIdType;
|
||||
|
||||
guint _nm_platform_signal_id_get (NMPlatformSignalIdType signal_type);
|
||||
|
||||
typedef enum {
|
||||
NM_PLATFORM_SIGNAL_NONE,
|
||||
NM_PLATFORM_SIGNAL_ADDED,
|
||||
|
|
|
|||
|
|
@ -1931,6 +1931,7 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = {
|
|||
.obj_type_name = "link",
|
||||
.addr_family = AF_UNSPEC,
|
||||
.rtm_gettype = RTM_GETLINK,
|
||||
.signal_type_id = NM_PLATFORM_SIGNAL_ID_LINK,
|
||||
.signal_type = NM_PLATFORM_SIGNAL_LINK_CHANGED,
|
||||
.cmd_obj_cmp = _vt_cmd_obj_cmp_link,
|
||||
.cmd_obj_copy = _vt_cmd_obj_copy_link,
|
||||
|
|
@ -1953,6 +1954,7 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = {
|
|||
.obj_type_name = "ip4-address",
|
||||
.addr_family = AF_INET,
|
||||
.rtm_gettype = RTM_GETADDR,
|
||||
.signal_type_id = NM_PLATFORM_SIGNAL_ID_IP4_ADDRESS,
|
||||
.signal_type = NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED,
|
||||
.cmd_obj_init_cache_id = _vt_cmd_obj_init_cache_id_ipx_address,
|
||||
.cmd_obj_stackinit_id = _vt_cmd_obj_stackinit_id_ip4_address,
|
||||
|
|
@ -1972,6 +1974,7 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = {
|
|||
.obj_type_name = "ip6-address",
|
||||
.addr_family = AF_INET6,
|
||||
.rtm_gettype = RTM_GETADDR,
|
||||
.signal_type_id = NM_PLATFORM_SIGNAL_ID_IP6_ADDRESS,
|
||||
.signal_type = NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED,
|
||||
.cmd_obj_init_cache_id = _vt_cmd_obj_init_cache_id_ipx_address,
|
||||
.cmd_obj_stackinit_id = _vt_cmd_obj_stackinit_id_ip6_address,
|
||||
|
|
@ -1991,6 +1994,7 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = {
|
|||
.obj_type_name = "ip4-route",
|
||||
.addr_family = AF_INET,
|
||||
.rtm_gettype = RTM_GETROUTE,
|
||||
.signal_type_id = NM_PLATFORM_SIGNAL_ID_IP4_ROUTE,
|
||||
.signal_type = NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED,
|
||||
.cmd_obj_init_cache_id = _vt_cmd_obj_init_cache_id_ipx_route,
|
||||
.cmd_obj_stackinit_id = _vt_cmd_obj_stackinit_id_ip4_route,
|
||||
|
|
@ -2010,6 +2014,7 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = {
|
|||
.obj_type_name = "ip6-route",
|
||||
.addr_family = AF_INET6,
|
||||
.rtm_gettype = RTM_GETROUTE,
|
||||
.signal_type_id = NM_PLATFORM_SIGNAL_ID_IP6_ROUTE,
|
||||
.signal_type = NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED,
|
||||
.cmd_obj_init_cache_id = _vt_cmd_obj_init_cache_id_ipx_route,
|
||||
.cmd_obj_stackinit_id = _vt_cmd_obj_stackinit_id_ip6_route,
|
||||
|
|
|
|||
|
|
@ -116,6 +116,7 @@ typedef struct {
|
|||
int rtm_gettype;
|
||||
int sizeof_data;
|
||||
int sizeof_public;
|
||||
NMPlatformSignalIdType signal_type_id;
|
||||
const char *obj_type_name;
|
||||
const char *signal_type;
|
||||
|
||||
|
|
|
|||
|
|
@ -32,7 +32,6 @@ PLATFORM_LDADD = \
|
|||
|
||||
noinst_PROGRAMS = \
|
||||
monitor \
|
||||
platform \
|
||||
test-link-fake \
|
||||
test-link-linux \
|
||||
test-address-fake \
|
||||
|
|
@ -49,9 +48,6 @@ EXTRA_DIST = test-common.h
|
|||
monitor_SOURCES = monitor.c $(PLATFORM_SOURCES)
|
||||
monitor_LDADD = $(PLATFORM_LDADD)
|
||||
|
||||
platform_SOURCES = platform.c $(PLATFORM_SOURCES)
|
||||
platform_LDADD = $(PLATFORM_LDADD)
|
||||
|
||||
test_link_fake_SOURCES = test-link.c $(TEST_SOURCES)
|
||||
test_link_fake_CPPFLAGS = \
|
||||
$(AM_CPPFLAGS) \
|
||||
|
|
|
|||
|
|
@ -1,892 +0,0 @@
|
|||
/* -*- 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) 2013 Red Hat, Inc.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netlink/route/addr.h>
|
||||
|
||||
#include "nm-default.h"
|
||||
#include "nm-platform.h"
|
||||
#include "nm-linux-platform.h"
|
||||
#include "nm-fake-platform.h"
|
||||
#include "nm-utils.h"
|
||||
|
||||
#define error(...) fprintf (stderr, __VA_ARGS__)
|
||||
|
||||
typedef gboolean boolean_t;
|
||||
typedef int decimal_t;
|
||||
typedef const char *string_t;
|
||||
|
||||
#define print_boolean(value) printf ("%s\n", value ? "yes" : "no")
|
||||
#define print_decimal(value) printf ("%d\n", value)
|
||||
#define print_string(value) printf ("%s\n", value)
|
||||
|
||||
static gboolean
|
||||
do_sysctl_set (char **argv)
|
||||
{
|
||||
return nm_platform_sysctl_set (NM_PLATFORM_GET, argv[0], argv[1]);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
do_sysctl_get (char **argv)
|
||||
{
|
||||
gs_free char *value = nm_platform_sysctl_get (NM_PLATFORM_GET, argv[0]);
|
||||
|
||||
printf ("%s\n", value);
|
||||
|
||||
return !!value;
|
||||
}
|
||||
|
||||
static int
|
||||
parse_ifindex (const char *str)
|
||||
{
|
||||
char *endptr;
|
||||
int ifindex = 0;
|
||||
|
||||
ifindex = strtol (str, &endptr, 10);
|
||||
|
||||
if (*endptr) {
|
||||
ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, str);
|
||||
}
|
||||
|
||||
return ifindex;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
do_link_get_all (char **argv)
|
||||
{
|
||||
GArray *links;
|
||||
NMPlatformLink *device;
|
||||
int i;
|
||||
|
||||
links = nm_platform_link_get_all (NM_PLATFORM_GET);
|
||||
for (i = 0; i < links->len; i++) {
|
||||
device = &g_array_index (links, NMPlatformLink, i);
|
||||
|
||||
printf ("%d: %s type %d\n", device->ifindex, device->name, device->type);
|
||||
}
|
||||
g_array_unref (links);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
do_dummy_add (char **argv)
|
||||
{
|
||||
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) == NM_PLATFORM_ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
do_bond_add (char **argv)
|
||||
{
|
||||
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) == NM_PLATFORM_ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
do_vlan_add (char **argv)
|
||||
{
|
||||
const char *name = *argv++;
|
||||
int parent = parse_ifindex (*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) == NM_PLATFORM_ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
do_link_exists (char **argv)
|
||||
{
|
||||
gboolean value = !!nm_platform_link_get_by_ifname (NM_PLATFORM_GET, argv[0]);
|
||||
|
||||
print_boolean (value);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#define LINK_CMD(cmdname) \
|
||||
static gboolean \
|
||||
do_link_##cmdname (char **argv) \
|
||||
{ \
|
||||
int ifindex = parse_ifindex (argv[0]); \
|
||||
return ifindex ? nm_platform_link_##cmdname (NM_PLATFORM_GET, ifindex) : FALSE; \
|
||||
}
|
||||
|
||||
#define LINK_CMD_GET_FULL(cmdname, type, cond) \
|
||||
static gboolean \
|
||||
do_link_##cmdname (char **argv) \
|
||||
{ \
|
||||
int ifindex = parse_ifindex (argv[0]); \
|
||||
if (ifindex) { \
|
||||
type##_t value = nm_platform_link_##cmdname (NM_PLATFORM_GET, ifindex); \
|
||||
if (cond) { \
|
||||
print_##type (value); \
|
||||
return TRUE; \
|
||||
} \
|
||||
} \
|
||||
return FALSE; \
|
||||
}
|
||||
#define LINK_CMD_GET(cmdname, type) LINK_CMD_GET_FULL (cmdname, type, TRUE);
|
||||
|
||||
LINK_CMD (delete)
|
||||
|
||||
/* do_link_delete_by_ifname:
|
||||
*
|
||||
* We don't need this as we allow ifname instead of ifindex anyway.
|
||||
*/
|
||||
|
||||
static gboolean
|
||||
do_link_get_ifindex (char **argv)
|
||||
{
|
||||
int ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, argv[0]);
|
||||
|
||||
if (ifindex)
|
||||
printf ("%d\n", ifindex);
|
||||
|
||||
return !!ifindex;
|
||||
}
|
||||
|
||||
LINK_CMD_GET_FULL (get_name, string, value)
|
||||
LINK_CMD_GET_FULL (get_type, decimal, value > 0)
|
||||
LINK_CMD_GET (is_software, boolean)
|
||||
LINK_CMD_GET (supports_slaves, boolean)
|
||||
|
||||
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)
|
||||
LINK_CMD_GET (is_up, boolean)
|
||||
LINK_CMD_GET (is_connected, boolean)
|
||||
LINK_CMD_GET (uses_arp, boolean)
|
||||
|
||||
static gboolean
|
||||
do_link_set_address (char **argv)
|
||||
{
|
||||
int ifindex = parse_ifindex (*argv++);
|
||||
char *hex = *argv++;
|
||||
int hexlen = strlen (hex);
|
||||
char address[hexlen/2];
|
||||
char *endptr;
|
||||
int i;
|
||||
|
||||
g_assert (!(hexlen % 2));
|
||||
|
||||
for (i = 0; i < sizeof (address); i++) {
|
||||
char digit[3];
|
||||
|
||||
digit[0] = hex[2*i];
|
||||
digit[1] = hex[2*i+1];
|
||||
digit[2] = '\0';
|
||||
|
||||
address[i] = strtoul (digit, &endptr, 16);
|
||||
g_assert (!*endptr);
|
||||
}
|
||||
|
||||
return nm_platform_link_set_address (NM_PLATFORM_GET, ifindex, address, sizeof (address));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
do_link_get_address (char **argv)
|
||||
{
|
||||
int ifindex = parse_ifindex (*argv++);
|
||||
const char *address;
|
||||
size_t length;
|
||||
int i;
|
||||
|
||||
address = nm_platform_link_get_address (NM_PLATFORM_GET, ifindex, &length);
|
||||
|
||||
if (!address || length <= 0)
|
||||
return FALSE;
|
||||
|
||||
for (i = 0; i < length; i++)
|
||||
printf ("%02x", address[i]);
|
||||
printf ("\n");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
do_link_set_mtu (char **argv)
|
||||
{
|
||||
int ifindex = parse_ifindex (*argv++);
|
||||
int mtu = strtoul (*argv++, NULL, 10);
|
||||
|
||||
return nm_platform_link_set_mtu (NM_PLATFORM_GET, ifindex, mtu);
|
||||
}
|
||||
|
||||
LINK_CMD_GET (get_mtu, decimal);
|
||||
LINK_CMD_GET (supports_carrier_detect, boolean)
|
||||
LINK_CMD_GET (supports_vlans, boolean)
|
||||
|
||||
static gboolean
|
||||
do_link_enslave (char **argv)
|
||||
{
|
||||
int master = parse_ifindex (*argv++);
|
||||
int slave = parse_ifindex (*argv++);
|
||||
|
||||
return nm_platform_link_enslave (NM_PLATFORM_GET, master, slave);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
do_link_release (char **argv)
|
||||
{
|
||||
int master = parse_ifindex (*argv++);
|
||||
int slave = parse_ifindex (*argv++);
|
||||
|
||||
return nm_platform_link_release (NM_PLATFORM_GET, master, slave);
|
||||
}
|
||||
|
||||
LINK_CMD_GET (get_master, decimal)
|
||||
|
||||
static gboolean
|
||||
do_master_set_option (char **argv)
|
||||
{
|
||||
int ifindex = parse_ifindex (*argv++);
|
||||
const char *option = *argv++;
|
||||
const char *value = *argv++;
|
||||
|
||||
return nm_platform_master_set_option (NM_PLATFORM_GET, ifindex, option, value);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
do_master_get_option (char **argv)
|
||||
{
|
||||
int ifindex = parse_ifindex (*argv++);
|
||||
const char *option = *argv++;
|
||||
gs_free char *value = nm_platform_master_get_option (NM_PLATFORM_GET, ifindex, option);
|
||||
|
||||
printf ("%s\n", value);
|
||||
|
||||
return !!value;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
do_slave_set_option (char **argv)
|
||||
{
|
||||
int ifindex = parse_ifindex (*argv++);
|
||||
const char *option = *argv++;
|
||||
const char *value = *argv++;
|
||||
|
||||
return nm_platform_slave_set_option (NM_PLATFORM_GET, ifindex, option, value);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
do_slave_get_option (char **argv)
|
||||
{
|
||||
int ifindex = parse_ifindex (*argv++);
|
||||
const char *option = *argv++;
|
||||
gs_free char *value = nm_platform_slave_get_option (NM_PLATFORM_GET, ifindex, option);
|
||||
|
||||
printf ("%s\n", value);
|
||||
|
||||
return !!value;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
do_vlan_get_info (char **argv)
|
||||
{
|
||||
int ifindex = parse_ifindex (*argv++);
|
||||
const NMPlatformLink *plink;
|
||||
const NMPlatformLnkVlan *plnk;
|
||||
|
||||
plnk = nm_platform_link_get_lnk_vlan (NM_PLATFORM_GET, ifindex, &plink);
|
||||
if (!plnk)
|
||||
return FALSE;
|
||||
|
||||
printf ("%d %d\n", plink->parent, plnk->id);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
do_vlan_set_ingress_map (char **argv)
|
||||
{
|
||||
int ifindex = parse_ifindex (*argv++);
|
||||
int from = strtol (*argv++, NULL, 10);
|
||||
int to = strtol (*argv++, NULL, 10);
|
||||
|
||||
return nm_platform_vlan_set_ingress_map (NM_PLATFORM_GET, ifindex, from, to);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
do_vlan_set_egress_map (char **argv)
|
||||
{
|
||||
int ifindex = parse_ifindex (*argv++);
|
||||
int from = strtol (*argv++, NULL, 10);
|
||||
int to = strtol (*argv++, NULL, 10);
|
||||
|
||||
return nm_platform_vlan_set_egress_map (NM_PLATFORM_GET, ifindex, from, to);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
do_tun_get_properties (char **argv)
|
||||
{
|
||||
int ifindex = parse_ifindex (*argv++);
|
||||
NMPlatformTunProperties props;
|
||||
|
||||
if (!nm_platform_tun_get_properties (NM_PLATFORM_GET, ifindex, &props))
|
||||
return FALSE;
|
||||
|
||||
printf ("mode: %s\n", props.mode);
|
||||
if (props.owner == -1)
|
||||
printf ("owner: none\n");
|
||||
else
|
||||
printf ("owner: %lu\n", (gulong) props.owner);
|
||||
if (props.group == -1)
|
||||
printf ("group: none\n");
|
||||
else
|
||||
printf ("group: %lu\n", (gulong) props.group);
|
||||
printf ("no-pi: ");
|
||||
print_boolean (props.no_pi);
|
||||
printf ("vnet-hdr: ");
|
||||
print_boolean (props.vnet_hdr);
|
||||
printf ("multi-queue: ");
|
||||
print_boolean (props.multi_queue);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
do_macvlan_get_properties (char **argv)
|
||||
{
|
||||
int ifindex = parse_ifindex (*argv++);
|
||||
const NMPlatformLink *plink;
|
||||
const NMPlatformLnkMacvlan *props;
|
||||
|
||||
props = nm_platform_link_get_lnk_macvlan (NM_PLATFORM_GET, ifindex, &plink);
|
||||
if (!props)
|
||||
return FALSE;
|
||||
|
||||
printf ("parent: %d\n", plink->parent);
|
||||
printf ("mode: %s\n", props->mode);
|
||||
printf ("no-promisc: ");
|
||||
print_boolean (props->no_promisc);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
do_vxlan_get_properties (char **argv)
|
||||
{
|
||||
int ifindex = parse_ifindex (*argv++);
|
||||
const NMPlatformLnkVxlan *props;
|
||||
char addrstr[INET6_ADDRSTRLEN];
|
||||
|
||||
props = nm_platform_link_get_lnk_vxlan (NM_PLATFORM_GET, ifindex, NULL);
|
||||
if (props)
|
||||
return FALSE;
|
||||
|
||||
printf ("parent-ifindex: %u\n", props->parent_ifindex);
|
||||
printf ("id: %u\n", props->id);
|
||||
if (props->group)
|
||||
inet_ntop (AF_INET, &props->group, addrstr, sizeof (addrstr));
|
||||
else if (props->group6.s6_addr[0])
|
||||
inet_ntop (AF_INET6, &props->group6, addrstr, sizeof (addrstr));
|
||||
else
|
||||
strcpy (addrstr, "-");
|
||||
printf ("group: %s\n", addrstr);
|
||||
if (props->local)
|
||||
inet_ntop (AF_INET, &props->local, addrstr, sizeof (addrstr));
|
||||
else if (props->local6.s6_addr[0])
|
||||
inet_ntop (AF_INET6, &props->local6, addrstr, sizeof (addrstr));
|
||||
else
|
||||
strcpy (addrstr, "-");
|
||||
printf ("local: %s\n", addrstr);
|
||||
printf ("tos: %u\n", props->tos);
|
||||
printf ("ttl: %u\n", props->ttl);
|
||||
printf ("learning: ");
|
||||
print_boolean (props->learning);
|
||||
printf ("ageing: %u\n", props->ageing);
|
||||
printf ("limit: %u\n", props->limit);
|
||||
printf ("dst-port: %u\n", props->dst_port);
|
||||
printf ("src-port-min: %u\n", props->src_port_min);
|
||||
printf ("src-port-max: %u\n", props->src_port_max);
|
||||
printf ("proxy: ");
|
||||
print_boolean (props->proxy);
|
||||
printf ("rsc: ");
|
||||
print_boolean (props->rsc);
|
||||
printf ("l2miss: ");
|
||||
print_boolean (props->l2miss);
|
||||
printf ("l3miss: ");
|
||||
print_boolean (props->l3miss);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
do_gre_get_properties (char **argv)
|
||||
{
|
||||
int ifindex = parse_ifindex (*argv++);
|
||||
const NMPlatformLnkGre *props;
|
||||
char addrstr[INET_ADDRSTRLEN];
|
||||
|
||||
props = nm_platform_link_get_lnk_gre (NM_PLATFORM_GET, ifindex, NULL);
|
||||
if (!props)
|
||||
return FALSE;
|
||||
|
||||
printf ("parent-ifindex: %u\n", props->parent_ifindex);
|
||||
printf ("input-flags: %u\n", props->input_flags);
|
||||
printf ("output-flags: %u\n", props->input_flags);
|
||||
printf ("input-key: %u\n", props->input_key);
|
||||
printf ("output-key: %u\n", props->output_key);
|
||||
if (props->local)
|
||||
inet_ntop (AF_INET, &props->local, addrstr, sizeof (addrstr));
|
||||
else
|
||||
strcpy (addrstr, "-");
|
||||
printf ("local: %s\n", addrstr);
|
||||
if (props->remote)
|
||||
inet_ntop (AF_INET, &props->remote, addrstr, sizeof (addrstr));
|
||||
else
|
||||
strcpy (addrstr, "-");
|
||||
printf ("remote: %s\n", addrstr);
|
||||
printf ("ttl: %u\n", props->ttl);
|
||||
printf ("tos: %u\n", props->tos);
|
||||
printf ("path-mtu-discovery: ");
|
||||
print_boolean (props->path_mtu_discovery);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
do_ip4_address_get_all (char **argv)
|
||||
{
|
||||
int ifindex = parse_ifindex (argv[0]);
|
||||
GArray *addresses;
|
||||
NMPlatformIP4Address *address;
|
||||
int i;
|
||||
|
||||
if (ifindex) {
|
||||
addresses = nm_platform_ip4_address_get_all (NM_PLATFORM_GET, ifindex);
|
||||
for (i = 0; i < addresses->len; i++) {
|
||||
address = &g_array_index (addresses, NMPlatformIP4Address, i);
|
||||
|
||||
printf ("%s", nm_utils_inet4_ntop (address->address, NULL));
|
||||
if (address->address != address->peer_address)
|
||||
printf (" peer %s", nm_utils_inet4_ntop (address->peer_address, NULL));
|
||||
printf ("/%d\n", address->plen);
|
||||
}
|
||||
g_array_unref (addresses);
|
||||
}
|
||||
|
||||
return !!ifindex;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
do_ip6_address_get_all (char **argv)
|
||||
{
|
||||
int ifindex = parse_ifindex (argv[0]);
|
||||
GArray *addresses;
|
||||
NMPlatformIP6Address *address;
|
||||
char addrstr[INET6_ADDRSTRLEN];
|
||||
int i;
|
||||
|
||||
if (ifindex) {
|
||||
addresses = nm_platform_ip6_address_get_all (NM_PLATFORM_GET, ifindex);
|
||||
for (i = 0; i < addresses->len; i++) {
|
||||
address = &g_array_index (addresses, NMPlatformIP6Address, i);
|
||||
inet_ntop (AF_INET6, &address->address, addrstr, sizeof (addrstr));
|
||||
printf ("%s/%d\n", addrstr, address->plen);
|
||||
}
|
||||
g_array_unref (addresses);
|
||||
}
|
||||
|
||||
return !!ifindex;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
parse_ip_address (int family, char *str, gpointer address, int *plen)
|
||||
{
|
||||
char *endptr;
|
||||
|
||||
if (plen)
|
||||
*plen = 0;
|
||||
|
||||
if (plen) {
|
||||
char *ptr = strchr (str, '/');
|
||||
if (ptr) {
|
||||
*ptr++ = '\0';
|
||||
*plen = strtol (ptr, &endptr, 10);
|
||||
if (*endptr)
|
||||
ptr = NULL;
|
||||
}
|
||||
if (!ptr) {
|
||||
error ("Bad format of IP address, expected address/plen.\n");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (inet_pton (family, str, address))
|
||||
return TRUE;
|
||||
|
||||
error ("Bad format of IP address, expected address%s.\n", plen ? "/plen" : "");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
typedef in_addr_t ip4_t;
|
||||
typedef struct in6_addr ip6_t;
|
||||
|
||||
#define parse_ip4_address(s, a, p) parse_ip_address (AF_INET, s, a, p)
|
||||
#define parse_ip6_address(s, a, p) parse_ip_address (AF_INET6, s, a, p)
|
||||
|
||||
static gboolean
|
||||
do_ip4_address_add (char **argv)
|
||||
{
|
||||
int ifindex = parse_ifindex (*argv++);
|
||||
ip4_t address;
|
||||
int plen;
|
||||
|
||||
if (ifindex && parse_ip4_address (*argv++, &address, &plen)) {
|
||||
guint32 lifetime = strtol (*argv++, NULL, 10);
|
||||
guint32 preferred = strtol (*argv++, NULL, 10);
|
||||
|
||||
gboolean value = nm_platform_ip4_address_add (NM_PLATFORM_GET, ifindex, address, plen, address, lifetime, preferred, NULL);
|
||||
return value;
|
||||
} else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
do_ip6_address_add (char **argv)
|
||||
{
|
||||
int ifindex = parse_ifindex (*argv++);
|
||||
ip6_t address;
|
||||
int plen;
|
||||
|
||||
if (ifindex && parse_ip6_address (*argv++, &address, &plen)) {
|
||||
guint32 lifetime = strtol (*argv++, NULL, 10);
|
||||
guint32 preferred = strtol (*argv++, NULL, 10);
|
||||
guint flags = 0; /* don't support flags */
|
||||
|
||||
gboolean value = nm_platform_ip6_address_add (NM_PLATFORM_GET, ifindex, address, plen, in6addr_any, lifetime, preferred, flags);
|
||||
return value;
|
||||
} else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#define ADDR_CMD_FULL(v, cmdname, print, ...) \
|
||||
static gboolean \
|
||||
do_##v##_address_##cmdname (char **argv) \
|
||||
{ \
|
||||
int ifindex = parse_ifindex (*argv++); \
|
||||
v##_t address; \
|
||||
int plen; \
|
||||
if (ifindex && parse_##v##_address (*argv++, &address, &plen)) { \
|
||||
gboolean value = !!nm_platform_##v##_address_##cmdname (NM_PLATFORM_GET, ifindex, address, plen, ##__VA_ARGS__); \
|
||||
if (print) { \
|
||||
print_boolean (value); \
|
||||
return TRUE; \
|
||||
} else \
|
||||
return value; \
|
||||
} else \
|
||||
return FALSE; \
|
||||
}
|
||||
#define ADDR_CMD(cmdname, ...) ADDR_CMD_FULL (ip4, cmdname, FALSE, address, ##__VA_ARGS__) ADDR_CMD_FULL (ip6, cmdname, FALSE)
|
||||
#define ADDR_CMD_PRINT(cmdname, ...) ADDR_CMD_FULL (ip4, cmdname, TRUE, ##__VA_ARGS__) ADDR_CMD_FULL (ip6, cmdname, TRUE)
|
||||
|
||||
ADDR_CMD (delete)
|
||||
ADDR_CMD_PRINT (get, address)
|
||||
|
||||
static gboolean
|
||||
do_ip4_route_get_all (char **argv)
|
||||
{
|
||||
int ifindex = parse_ifindex (argv[0]);
|
||||
GArray *routes;
|
||||
NMPlatformIP4Route *route;
|
||||
char networkstr[INET_ADDRSTRLEN], gatewaystr[INET_ADDRSTRLEN];
|
||||
int i;
|
||||
|
||||
if (ifindex) {
|
||||
routes = nm_platform_ip4_route_get_all (NM_PLATFORM_GET, ifindex, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT | NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT);
|
||||
for (i = 0; i < routes->len; i++) {
|
||||
route = &g_array_index (routes, NMPlatformIP4Route, i);
|
||||
inet_ntop (AF_INET, &route->network, networkstr, sizeof (networkstr));
|
||||
inet_ntop (AF_INET, &route->gateway, gatewaystr, sizeof (gatewaystr));
|
||||
printf ("%s/%d via %s metric %d\n",
|
||||
networkstr, route->plen, gatewaystr, route->metric);
|
||||
}
|
||||
g_array_unref (routes);
|
||||
}
|
||||
|
||||
return !!ifindex;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
do_ip6_route_get_all (char **argv)
|
||||
{
|
||||
int ifindex = parse_ifindex (argv[0]);
|
||||
GArray *routes;
|
||||
NMPlatformIP6Route *route;
|
||||
char networkstr[INET6_ADDRSTRLEN], gatewaystr[INET6_ADDRSTRLEN];
|
||||
int i;
|
||||
|
||||
if (ifindex) {
|
||||
routes = nm_platform_ip6_route_get_all (NM_PLATFORM_GET, ifindex, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT | NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT);
|
||||
for (i = 0; i < routes->len; i++) {
|
||||
route = &g_array_index (routes, NMPlatformIP6Route, i);
|
||||
inet_ntop (AF_INET6, &route->network, networkstr, sizeof (networkstr));
|
||||
inet_ntop (AF_INET6, &route->gateway, gatewaystr, sizeof (gatewaystr));
|
||||
printf ("%s/%d via %s metric %d\n",
|
||||
networkstr, route->plen, gatewaystr, route->metric);
|
||||
}
|
||||
g_array_unref (routes);
|
||||
}
|
||||
|
||||
return !!ifindex;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
do_ip4_route_add (char **argv)
|
||||
{
|
||||
int ifindex = parse_ifindex (*argv++);
|
||||
in_addr_t network, gateway;
|
||||
int plen, metric, mss;
|
||||
|
||||
parse_ip4_address (*argv++, &network, &plen);
|
||||
parse_ip4_address (*argv++, &gateway, NULL);
|
||||
metric = strtol (*argv++, NULL, 10);
|
||||
mss = strtol (*argv++, NULL, 10);
|
||||
|
||||
return nm_platform_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER,
|
||||
network, plen, gateway, 0,
|
||||
metric, mss);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
do_ip6_route_add (char **argv)
|
||||
{
|
||||
int ifindex = parse_ifindex (*argv++);
|
||||
struct in6_addr network, gateway;
|
||||
int plen, metric, mss;
|
||||
|
||||
parse_ip6_address (*argv++, &network, &plen);
|
||||
parse_ip6_address (*argv++, &gateway, NULL);
|
||||
metric = strtol (*argv++, NULL, 10);
|
||||
mss = strtol (*argv++, NULL, 10);
|
||||
return nm_platform_ip6_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER,
|
||||
network, plen, gateway,
|
||||
metric, mss);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
do_ip4_route_delete (char **argv)
|
||||
{
|
||||
int ifindex = parse_ifindex (*argv++);
|
||||
in_addr_t network;
|
||||
int plen, metric;
|
||||
|
||||
parse_ip4_address (*argv++, &network, &plen);
|
||||
metric = strtol (*argv++, NULL, 10);
|
||||
|
||||
return nm_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, plen, metric);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
do_ip6_route_delete (char **argv)
|
||||
{
|
||||
int ifindex = parse_ifindex (*argv++);
|
||||
struct in6_addr network;
|
||||
int plen, metric;
|
||||
|
||||
parse_ip6_address (*argv++, &network, &plen);
|
||||
metric = strtol (*argv++, NULL, 10);
|
||||
|
||||
return nm_platform_ip6_route_delete (NM_PLATFORM_GET, ifindex, network, plen, metric);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
do_ip4_route_get (char **argv)
|
||||
{
|
||||
int ifindex = parse_ifindex (*argv++);
|
||||
in_addr_t network;
|
||||
int plen, metric;
|
||||
|
||||
parse_ip4_address (*argv++, &network, &plen);
|
||||
metric = strtol (*argv++, NULL, 10);
|
||||
|
||||
print_boolean (!!nm_platform_ip4_route_get (NM_PLATFORM_GET, ifindex, network, plen, metric));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
do_ip6_route_get (char **argv)
|
||||
{
|
||||
int ifindex = parse_ifindex (*argv++);
|
||||
struct in6_addr network;
|
||||
int plen, metric;
|
||||
|
||||
parse_ip6_address (*argv++, &network, &plen);
|
||||
metric = strtol (*argv++, NULL, 10);
|
||||
|
||||
print_boolean (!!nm_platform_ip6_route_get (NM_PLATFORM_GET, ifindex, network, plen, metric));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
const char *help;
|
||||
int (*handler) (char **argv);
|
||||
int argc;
|
||||
const char *arghelp;
|
||||
} command_t;
|
||||
|
||||
static const command_t commands[] = {
|
||||
{ "sysctl-set", "get /proc/sys or /sys value", do_sysctl_set, 2, "<path> <value>" },
|
||||
{ "sysctl-get", "get /proc/sys or /sys value", do_sysctl_get, 1, "<value>" },
|
||||
{ "link-get-all", "print all links", do_link_get_all, 0, "" },
|
||||
{ "dummy-add", "add dummy interface", do_dummy_add, 1, "<ifname>" },
|
||||
{ "bridge-add", "add bridge interface", do_bridge_add, 1, "<ifname>" },
|
||||
{ "bond-add", "add bond interface", do_bond_add, 1, "<ifname>" },
|
||||
{ "team-add", "add team interface", do_team_add, 1, "<ifname>" },
|
||||
{ "vlan-add", "add vlan interface", do_vlan_add, 4, "<ifname> <parent> <vlanid> <vlanflags>" },
|
||||
{ "link-exists", "check ifname for existance", do_link_exists, 1, "<ifname>" },
|
||||
{ "link-delete", "delete interface", do_link_delete, 1, "<ifname/ifindex>" },
|
||||
{ "link-get-ifindex>", "get interface index", do_link_get_ifindex, 1, "<ifname>" },
|
||||
{ "link-get-name", "get interface name", do_link_get_name, 1, "<ifindex>" },
|
||||
{ "link-get-type", "get interface type", do_link_get_type, 1, "<ifname/ifindex>" },
|
||||
{ "link-is-software", "check if interface is a software one", do_link_is_software, 1, "<ifname/ifindex>" },
|
||||
{ "link-supports-slaves", "check if interface supports slaves", do_link_supports_slaves, 1, "<ifname/ifindex>" },
|
||||
{ "link-set-up", "set interface up", do_link_set_up, 1, "<ifname/ifindex>" },
|
||||
{ "link-set-down", "set interface down", do_link_set_down, 1, "<ifname/ifindex>" },
|
||||
{ "link-set-arp", "activate interface arp", do_link_set_arp, 1, "<ifname/ifindex>" },
|
||||
{ "link-set-noarp", "deactivate interface arp", do_link_set_noarp, 1, "<ifname/ifindex>" },
|
||||
{ "link-is-up", "check if interface is up", do_link_is_up, 1, "<ifname/ifindex>" },
|
||||
{ "link-is-connected", "check interface carrier", do_link_is_connected, 1, "<ifname/ifindex>" },
|
||||
{ "link-uses-arp", "check whether interface uses arp", do_link_uses_arp, 1, "<ifname/ifindex>" },
|
||||
{ "link-get-address", "print link address", do_link_get_address, 1, "<ifname/ifindex>" },
|
||||
{ "link-set-address", "set link address", do_link_set_address, 2, "<ifname/ifindex> <hex>" },
|
||||
{ "link-get-mtu", "print link mtu", do_link_get_mtu, 1, "<ifname/ifindex>" },
|
||||
{ "link-set-mtu", "set link mtu", do_link_set_mtu, 2, "<ifname/ifindex> <mtu>" },
|
||||
{ "link-supports-carrier-detect", "check whether interface supports carrier detect",
|
||||
do_link_supports_carrier_detect, 1, "<ifname/ifindex>" },
|
||||
{ "link-supports-vlans", "check whether interface supports VLANs",
|
||||
do_link_supports_vlans, 1, "<ifname/ifindex>" },
|
||||
{ "link-enslave", "enslave slave interface with master", do_link_enslave, 2, "<master> <slave>" },
|
||||
{ "link-release", "release save interface from master", do_link_release, 2, "<master> <slave>" },
|
||||
{ "link-get-master", "print master interface of a slave", do_link_get_master, 1, "<ifname/ifindex>" },
|
||||
{ "link-master-set-option", "set master option", do_master_set_option, 3,
|
||||
"<ifname/ifindex> <option> <value>" },
|
||||
{ "link-master-get-option", "get master option", do_master_get_option, 2,
|
||||
"<ifname/ifindex> <option>" },
|
||||
{ "link-slave-set-option", "set slave option", do_slave_set_option, 3,
|
||||
"<ifname/ifindex> <option>" },
|
||||
{ "link-slave-get-option", "get slave option", do_slave_get_option, 2,
|
||||
"<ifname/ifindex> <option>" },
|
||||
{ "vlan-get-info", "get vlan info", do_vlan_get_info, 1, "<ifname/ifindex>" },
|
||||
{ "vlan-set-ingress-map", "set vlan ingress map", do_vlan_set_ingress_map, 3,
|
||||
"<ifname/ifindex> <from> <to>" },
|
||||
{ "vlan-set-egress-map", "set vlan egress map", do_vlan_set_egress_map, 3,
|
||||
"<ifname/ifindex> <from> <to>" },
|
||||
{ "tun-get-properties", "get tun/tap properties", do_tun_get_properties, 1,
|
||||
"<ifname/ifindex>" },
|
||||
{ "macvlan-get-properties", "get macvlan properties", do_macvlan_get_properties, 1,
|
||||
"<ifname/ifindex>" },
|
||||
{ "vxlan-get-properties", "get vxlan properties", do_vxlan_get_properties, 1,
|
||||
"<ifname/ifindex>" },
|
||||
{ "gre-get-properties", "get gre properties", do_gre_get_properties, 1,
|
||||
"<ifname/ifindex>" },
|
||||
{ "ip4-address-get-all", "print all IPv4 addresses", do_ip4_address_get_all, 1, "<ifname/ifindex>" },
|
||||
{ "ip6-address-get-all", "print all IPv6 addresses", do_ip6_address_get_all, 1, "<ifname/ifindex>" },
|
||||
{ "ip4-address-add", "add IPv4 address", do_ip4_address_add, 4, "<ifname/ifindex> <address>/<plen> <lifetime> <>" },
|
||||
{ "ip6-address-add", "add IPv6 address", do_ip6_address_add, 4, "<ifname/ifindex> <address>/<plen> <lifetime> [<flags>] <>" },
|
||||
{ "ip4-address-delete", "delete IPv4 address", do_ip4_address_delete, 2,
|
||||
"<ifname/ifindex> <address>/<plen>" },
|
||||
{ "ip6-address-delete", "delete IPv6 address", do_ip6_address_delete, 2,
|
||||
"<ifname/ifindex> <address>/<plen>" },
|
||||
{ "ip4-address-exists", "check for existence of IPv4 address", do_ip4_address_get, 2,
|
||||
"<ifname/ifindex> <address>/<plen>" },
|
||||
{ "ip6-address-exists", "check for existence of IPv6 address", do_ip6_address_get, 2,
|
||||
"<ifname/ifindex> <address>/<plen>" },
|
||||
{ "ip4-route-get-all", "print all IPv4 routes", do_ip4_route_get_all, 1, "<ifname/ifindex>" },
|
||||
{ "ip6-route-get-all", "print all IPv6 routes", do_ip6_route_get_all, 1, "<ifname/ifindex>" },
|
||||
{ "ip4-route-add", "add IPv4 route", do_ip4_route_add, 5,
|
||||
"<ifname/ifindex> <network>/<plen> <gateway> <metric> <mss>" },
|
||||
{ "ip6-route-add", "add IPv6 route", do_ip6_route_add, 5,
|
||||
"<ifname/ifindex> <network>/<plen> <gateway> <metric> <mss>" },
|
||||
{ "ip4-route-delete", "delete IPv4 route", do_ip4_route_delete, 3,
|
||||
"<ifname/ifindex> <network>/<plen> <metric>" },
|
||||
{ "ip6-route-delete", "delete IPv6 route", do_ip6_route_delete, 3,
|
||||
"<ifname/ifindex> <network>/<plen> <metric>" },
|
||||
{ "ip4-route-exists", "check for existence of IPv4 route", do_ip4_route_get, 3,
|
||||
"<ifname/ifindex> <network>/<plen> <metric>" },
|
||||
{ "ip6-route-exists", "check for existence of IPv6 route", do_ip6_route_get, 3,
|
||||
"<ifname/ifindex> <network>/<plen> <metric>" },
|
||||
{ NULL, NULL, NULL, 0, NULL },
|
||||
};
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
const char *arg0 = *argv++;
|
||||
const command_t *command = NULL;
|
||||
gboolean status = TRUE;
|
||||
|
||||
nm_g_type_init ();
|
||||
|
||||
if (*argv && !g_strcmp0 (argv[1], "--fake")) {
|
||||
nm_fake_platform_setup ();
|
||||
} else
|
||||
nm_linux_platform_setup ();
|
||||
|
||||
if (*argv)
|
||||
for (command = commands; command->name; command++)
|
||||
if (g_str_has_prefix (command->name, *argv))
|
||||
break;
|
||||
|
||||
if (command && command->name) {
|
||||
argv++;
|
||||
if (g_strv_length (argv) == command->argc)
|
||||
status = command->handler (argv);
|
||||
else {
|
||||
error ("Wrong number of arguments to '%s' (expected %d).\n\nUsage: %s %s %s\n-- %s\n",
|
||||
command->name, command->argc,
|
||||
arg0, command->name, command->arghelp, command->help);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
} else {
|
||||
error ("Usage: %s COMMAND\n\n", arg0);
|
||||
error ("COMMAND\n");
|
||||
for (command = commands; command->name; command++)
|
||||
error (" %s %s\n -- %s\n", command->name, command->arghelp, command->help);
|
||||
error ("\n");
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -16,7 +16,7 @@ static int EX = -1;
|
|||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
ip4_address_callback (NMPlatform *platform, NMPObjectType obj_type, int ifindex, NMPlatformIP4Address *received, NMPlatformSignalChangeType change_type, NMPlatformReason reason, SignalData *data)
|
||||
ip4_address_callback (NMPlatform *platform, NMPObjectType obj_type, int ifindex, NMPlatformIP4Address *received, NMPlatformSignalChangeType change_type, SignalData *data)
|
||||
{
|
||||
g_assert (received);
|
||||
g_assert_cmpint (received->ifindex, ==, ifindex);
|
||||
|
|
@ -36,7 +36,7 @@ ip4_address_callback (NMPlatform *platform, NMPObjectType obj_type, int ifindex,
|
|||
}
|
||||
|
||||
static void
|
||||
ip6_address_callback (NMPlatform *platform, NMPObjectType obj_type, int ifindex, NMPlatformIP6Address *received, NMPlatformSignalChangeType change_type, NMPlatformReason reason, SignalData *data)
|
||||
ip6_address_callback (NMPlatform *platform, NMPObjectType obj_type, int ifindex, NMPlatformIP6Address *received, NMPlatformSignalChangeType change_type, SignalData *data)
|
||||
{
|
||||
g_assert (received);
|
||||
g_assert_cmpint (received->ifindex, ==, ifindex);
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
#include <sys/mount.h>
|
||||
#include <sched.h>
|
||||
#include <sys/wait.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "test-common.h"
|
||||
|
||||
|
|
@ -107,7 +109,7 @@ _free_signal (const char *file, int line, const char *func, SignalData *data)
|
|||
}
|
||||
|
||||
void
|
||||
link_callback (NMPlatform *platform, NMPObjectType obj_type, int ifindex, NMPlatformLink *received, NMPlatformSignalChangeType change_type, NMPlatformReason reason, SignalData *data)
|
||||
link_callback (NMPlatform *platform, NMPObjectType obj_type, int ifindex, NMPlatformLink *received, NMPlatformSignalChangeType change_type, SignalData *data)
|
||||
{
|
||||
GArray *links;
|
||||
NMPlatformLink *cached;
|
||||
|
|
@ -297,7 +299,6 @@ _wait_for_signal_cb (NMPlatform *platform,
|
|||
int ifindex,
|
||||
NMPlatformLink *plink,
|
||||
NMPlatformSignalChangeType change_type,
|
||||
NMPlatformReason reason,
|
||||
gpointer user_data)
|
||||
{
|
||||
WaitForSignalData *data = user_data;
|
||||
|
|
@ -367,13 +368,13 @@ nmtstp_wait_for_signal_until (gint64 until_ms)
|
|||
}
|
||||
|
||||
const NMPlatformLink *
|
||||
nmtstp_wait_for_link (const char *ifname, guint timeout_ms)
|
||||
nmtstp_wait_for_link (const char *ifname, NMLinkType expected_link_type, guint timeout_ms)
|
||||
{
|
||||
return nmtstp_wait_for_link_until (ifname, nm_utils_get_monotonic_timestamp_ms () + timeout_ms);
|
||||
return nmtstp_wait_for_link_until (ifname, expected_link_type, nm_utils_get_monotonic_timestamp_ms () + timeout_ms);
|
||||
}
|
||||
|
||||
const NMPlatformLink *
|
||||
nmtstp_wait_for_link_until (const char *ifname, gint64 until_ms)
|
||||
nmtstp_wait_for_link_until (const char *ifname, NMLinkType expected_link_type, gint64 until_ms)
|
||||
{
|
||||
const NMPlatformLink *plink;
|
||||
gint64 now;
|
||||
|
|
@ -382,7 +383,8 @@ nmtstp_wait_for_link_until (const char *ifname, gint64 until_ms)
|
|||
now = nm_utils_get_monotonic_timestamp_ms ();
|
||||
|
||||
plink = nm_platform_link_get_by_ifname (NM_PLATFORM_GET, ifname);
|
||||
if (plink)
|
||||
if ( plink
|
||||
&& (expected_link_type == NM_LINK_TYPE_NONE || plink->type == expected_link_type))
|
||||
return plink;
|
||||
|
||||
if (until_ms < now)
|
||||
|
|
@ -403,10 +405,8 @@ nmtstp_assert_wait_for_link_until (const char *ifname, NMLinkType expected_link_
|
|||
{
|
||||
const NMPlatformLink *plink;
|
||||
|
||||
plink = nmtstp_wait_for_link_until (ifname, until_ms);
|
||||
plink = nmtstp_wait_for_link_until (ifname, expected_link_type, until_ms);
|
||||
g_assert (plink);
|
||||
if (expected_link_type != NM_LINK_TYPE_NONE)
|
||||
g_assert_cmpint (plink->type, ==, expected_link_type);
|
||||
return plink;
|
||||
}
|
||||
|
||||
|
|
@ -880,6 +880,169 @@ nmtstp_link_set_updown (gboolean external_command,
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
struct _NMTstpNamespaceHandle {
|
||||
pid_t pid;
|
||||
int pipe_fd;
|
||||
};
|
||||
|
||||
NMTstpNamespaceHandle *
|
||||
nmtstp_namespace_create (int unshare_flags, GError **error)
|
||||
{
|
||||
NMTstpNamespaceHandle *ns_handle;
|
||||
int e;
|
||||
int errsv;
|
||||
pid_t pid, pid2;
|
||||
int pipefd_c2p[2];
|
||||
int pipefd_p2c[2];
|
||||
ssize_t r;
|
||||
|
||||
e = pipe (pipefd_c2p);
|
||||
if (e != 0) {
|
||||
errsv = errno;
|
||||
g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
|
||||
"pipe() failed with %d (%s)", errsv, strerror (errsv));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
e = pipe (pipefd_p2c);
|
||||
if (e != 0) {
|
||||
errsv = errno;
|
||||
g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
|
||||
"pipe() failed with %d (%s)", errsv, strerror (errsv));
|
||||
close (pipefd_c2p[0]);
|
||||
close (pipefd_c2p[1]);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pid = fork ();
|
||||
if (pid < 0) {
|
||||
errsv = errno;
|
||||
g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
|
||||
"fork() failed with %d (%s)", errsv, strerror (errsv));
|
||||
close (pipefd_c2p[0]);
|
||||
close (pipefd_c2p[1]);
|
||||
close (pipefd_p2c[0]);
|
||||
close (pipefd_p2c[1]);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (pid == 0) {
|
||||
char read_buf[1];
|
||||
|
||||
close (pipefd_c2p[0]); /* close read-end */
|
||||
close (pipefd_p2c[1]); /* close write-end */
|
||||
|
||||
if (unshare (unshare_flags) != 0) {
|
||||
errsv = errno;
|
||||
if (errsv == 0)
|
||||
errsv = -1;
|
||||
} else
|
||||
errsv = 0;
|
||||
|
||||
/* sync with parent process and send result. */
|
||||
do {
|
||||
r = write (pipefd_c2p[1], &errsv, sizeof (errsv));
|
||||
} while (r < 0 && errno == EINTR);
|
||||
if (r != sizeof (errsv)) {
|
||||
errsv = errno;
|
||||
if (errsv == 0)
|
||||
errsv = -2;
|
||||
}
|
||||
close (pipefd_c2p[1]);
|
||||
|
||||
/* wait until parent process terminates (or kills us). */
|
||||
if (errsv == 0) {
|
||||
do {
|
||||
r = read (pipefd_p2c[0], read_buf, sizeof (read_buf));
|
||||
} while (r < 0 && errno == EINTR);
|
||||
}
|
||||
close (pipefd_p2c[0]);
|
||||
_exit (0);
|
||||
}
|
||||
|
||||
close (pipefd_c2p[1]); /* close write-end */
|
||||
close (pipefd_p2c[0]); /* close read-end */
|
||||
|
||||
/* sync with child process. */
|
||||
do {
|
||||
r = read (pipefd_c2p[0], &errsv, sizeof (errsv));
|
||||
} while (r < 0 && errno == EINTR);
|
||||
|
||||
close (pipefd_c2p[0]);
|
||||
|
||||
if ( r != sizeof (errsv)
|
||||
|| errsv != 0) {
|
||||
int status;
|
||||
|
||||
if (r != sizeof (errsv)) {
|
||||
g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
|
||||
"child process failed for unknown reason");
|
||||
} else {
|
||||
g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
|
||||
"child process signaled failure %d (%s)", errsv, strerror (errsv));
|
||||
}
|
||||
close (pipefd_p2c[1]);
|
||||
kill (pid, SIGKILL);
|
||||
do {
|
||||
pid2 = waitpid (pid, &status, 0);
|
||||
} while (pid2 == -1 && errno == EINTR);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ns_handle = g_new0 (NMTstpNamespaceHandle, 1);
|
||||
ns_handle->pid = pid;
|
||||
ns_handle->pipe_fd = pipefd_p2c[1];
|
||||
return ns_handle;
|
||||
}
|
||||
|
||||
pid_t
|
||||
nmtstp_namespace_handle_get_pid (NMTstpNamespaceHandle *ns_handle)
|
||||
{
|
||||
g_return_val_if_fail (ns_handle, 0);
|
||||
g_return_val_if_fail (ns_handle->pid > 0, 0);
|
||||
|
||||
return ns_handle->pid;
|
||||
}
|
||||
|
||||
void
|
||||
nmtstp_namespace_handle_release (NMTstpNamespaceHandle *ns_handle)
|
||||
{
|
||||
pid_t pid;
|
||||
int status;
|
||||
|
||||
if (!ns_handle)
|
||||
return;
|
||||
|
||||
g_return_if_fail (ns_handle->pid > 0);
|
||||
|
||||
close (ns_handle->pipe_fd);
|
||||
ns_handle->pipe_fd = 0;
|
||||
|
||||
kill (ns_handle->pid, SIGKILL);
|
||||
|
||||
do {
|
||||
pid = waitpid (ns_handle->pid, &status, 0);
|
||||
} while (pid == -1 && errno == EINTR);
|
||||
ns_handle->pid = 0;
|
||||
|
||||
g_free (ns_handle);
|
||||
}
|
||||
|
||||
int
|
||||
nmtstp_namespace_get_fd_for_process (pid_t pid, const char *ns_name)
|
||||
{
|
||||
char p[1000];
|
||||
|
||||
g_return_val_if_fail (pid > 0, 0);
|
||||
g_return_val_if_fail (ns_name && ns_name[0] && strlen (ns_name) < 50, 0);
|
||||
|
||||
nm_sprintf_buf (p, "/proc/%lu/ns/%s", (long unsigned) pid, ns_name);
|
||||
|
||||
return open(p, O_RDONLY);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
NMTST_DEFINE();
|
||||
|
||||
static gboolean
|
||||
|
|
|
|||
|
|
@ -46,6 +46,19 @@ typedef struct {
|
|||
gboolean nmtstp_is_root_test (void);
|
||||
gboolean nmtstp_is_sysfs_writable (void);
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
typedef struct _NMTstpNamespaceHandle NMTstpNamespaceHandle;
|
||||
|
||||
NMTstpNamespaceHandle *nmtstp_namespace_create (int flags, GError **error);
|
||||
|
||||
void nmtstp_namespace_handle_release (NMTstpNamespaceHandle *handle);
|
||||
pid_t nmtstp_namespace_handle_get_pid (NMTstpNamespaceHandle *handle);
|
||||
|
||||
int nmtstp_namespace_get_fd_for_process (pid_t pid, const char *ns_name);
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
SignalData *add_signal_full (const char *name, NMPlatformSignalChangeType change_type, GCallback callback, int ifindex, const char *ifname);
|
||||
#define add_signal(name, change_type, callback) add_signal_full (name, change_type, (GCallback) callback, 0, NULL)
|
||||
#define add_signal_ifindex(name, change_type, callback, ifindex) add_signal_full (name, change_type, (GCallback) callback, ifindex, NULL)
|
||||
|
|
@ -68,15 +81,15 @@ gboolean ip4_route_exists (const char *ifname, guint32 network, int plen, guint3
|
|||
void _assert_ip4_route_exists (const char *file, guint line, const char *func, gboolean exists, const char *ifname, guint32 network, int plen, guint32 metric);
|
||||
#define assert_ip4_route_exists(exists, ifname, network, plen, metric) _assert_ip4_route_exists (__FILE__, __LINE__, G_STRFUNC, exists, ifname, network, plen, metric)
|
||||
|
||||
void link_callback (NMPlatform *platform, NMPObjectType obj_type, int ifindex, NMPlatformLink *received, NMPlatformSignalChangeType change_type, NMPlatformReason reason, SignalData *data);
|
||||
void link_callback (NMPlatform *platform, NMPObjectType obj_type, int ifindex, NMPlatformLink *received, NMPlatformSignalChangeType change_type, SignalData *data);
|
||||
|
||||
int nmtstp_run_command (const char *format, ...) __attribute__((__format__ (__printf__, 1, 2)));
|
||||
#define nmtstp_run_command_check(format, ...) do { g_assert_cmpint (nmtstp_run_command (format, __VA_ARGS__), ==, 0); } while (0)
|
||||
#define nmtstp_run_command_check(...) do { g_assert_cmpint (nmtstp_run_command (__VA_ARGS__), ==, 0); } while (0)
|
||||
|
||||
gboolean nmtstp_wait_for_signal (guint timeout_ms);
|
||||
gboolean nmtstp_wait_for_signal_until (gint64 until_ms);
|
||||
const NMPlatformLink *nmtstp_wait_for_link (const char *ifname, guint timeout_ms);
|
||||
const NMPlatformLink *nmtstp_wait_for_link_until (const char *ifname, gint64 until_ms);
|
||||
const NMPlatformLink *nmtstp_wait_for_link (const char *ifname, NMLinkType expected_link_type, guint timeout_ms);
|
||||
const NMPlatformLink *nmtstp_wait_for_link_until (const char *ifname, NMLinkType expected_link_type, gint64 until_ms);
|
||||
|
||||
const NMPlatformLink *nmtstp_assert_wait_for_link (const char *ifname, NMLinkType expected_link_type, guint timeout_ms);
|
||||
const NMPlatformLink *nmtstp_assert_wait_for_link_until (const char *ifname, NMLinkType expected_link_type, gint64 until_ms);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
#include "config.h"
|
||||
|
||||
#include <sched.h>
|
||||
|
||||
#include "nmp-object.h"
|
||||
|
||||
#include "test-common.h"
|
||||
|
|
@ -136,7 +138,6 @@ test_link_changed_signal_cb (NMPlatform *platform,
|
|||
int ifindex,
|
||||
const NMPlatformIP4Route *route,
|
||||
NMPlatformSignalChangeType change_type,
|
||||
NMPlatformReason reason,
|
||||
gboolean *p_test_link_changed_signal_arg)
|
||||
{
|
||||
/* test invocation of platform signals with multiple listeners
|
||||
|
|
@ -159,9 +160,6 @@ test_link_changed_signal_cb (NMPlatform *platform,
|
|||
g_assert_cmpint ((gint64) change_type, !=, (gint64) 0);
|
||||
g_assert_cmpint (change_type, !=, NM_PLATFORM_SIGNAL_NONE);
|
||||
|
||||
g_assert_cmpint ((gint64) reason, !=, (gint64) 0);
|
||||
g_assert_cmpint (reason, !=, NM_PLATFORM_REASON_NONE);
|
||||
|
||||
*p_test_link_changed_signal_arg = TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -287,10 +285,14 @@ test_slave (int master, int type, SignalData *master_changed)
|
|||
}
|
||||
|
||||
/* Release */
|
||||
ensure_no_signal (link_added);
|
||||
ensure_no_signal (link_changed);
|
||||
ensure_no_signal (link_removed);
|
||||
g_assert (nm_platform_link_release (NM_PLATFORM_GET, master, ifindex));
|
||||
g_assert_cmpint (nm_platform_link_get_master (NM_PLATFORM_GET, ifindex), ==, 0);
|
||||
accept_signals (link_added, 0, 1);
|
||||
accept_signals (link_changed, 1, 3);
|
||||
accept_signals (link_removed, 0, 1);
|
||||
accept_signals (master_changed, 1, 2);
|
||||
|
||||
ensure_no_signal (master_changed);
|
||||
|
|
@ -302,7 +304,9 @@ test_slave (int master, int type, SignalData *master_changed)
|
|||
ensure_no_signal (master_changed);
|
||||
|
||||
/* Remove */
|
||||
ensure_no_signal (link_added);
|
||||
ensure_no_signal (link_changed);
|
||||
ensure_no_signal (link_removed);
|
||||
g_assert (nm_platform_link_delete (NM_PLATFORM_GET, ifindex));
|
||||
accept_signals (master_changed, 0, 1);
|
||||
accept_signals (link_changed, 0, 1);
|
||||
|
|
@ -1371,6 +1375,181 @@ test_vlan_set_xgress (void)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
test_nl_bugs_veth (void)
|
||||
{
|
||||
const char *IFACE_VETH0 = "nm-test-veth0";
|
||||
const char *IFACE_VETH1 = "nm-test-veth1";
|
||||
int ifindex_veth0, ifindex_veth1;
|
||||
int i;
|
||||
const NMPlatformLink *pllink_veth0, *pllink_veth1;
|
||||
gs_free_error GError *error = NULL;
|
||||
NMTstpNamespaceHandle *ns_handle = NULL;
|
||||
|
||||
/* create veth pair. */
|
||||
nmtstp_run_command_check ("ip link add dev %s type veth peer name %s", IFACE_VETH0, IFACE_VETH1);
|
||||
ifindex_veth0 = nmtstp_assert_wait_for_link (IFACE_VETH0, NM_LINK_TYPE_VETH, 100)->ifindex;
|
||||
ifindex_veth1 = nmtstp_assert_wait_for_link (IFACE_VETH1, NM_LINK_TYPE_VETH, 100)->ifindex;
|
||||
|
||||
/* assert that nm_platform_veth_get_properties() returns the expected peer ifindexes. */
|
||||
g_assert (nm_platform_veth_get_properties (NM_PLATFORM_GET, ifindex_veth0, &i));
|
||||
g_assert_cmpint (i, ==, ifindex_veth1);
|
||||
|
||||
g_assert (nm_platform_veth_get_properties (NM_PLATFORM_GET, ifindex_veth1, &i));
|
||||
g_assert_cmpint (i, ==, ifindex_veth0);
|
||||
|
||||
/* assert that NMPlatformLink.parent is the peer-ifindex. */
|
||||
pllink_veth0 = nm_platform_link_get (NM_PLATFORM_GET, ifindex_veth0);
|
||||
g_assert (pllink_veth0);
|
||||
if (pllink_veth0->parent == 0) {
|
||||
/* pre-4.1 kernels don't support exposing the veth peer as IFA_LINK. skip the remainder
|
||||
* of the test. */
|
||||
goto out;
|
||||
}
|
||||
g_assert_cmpint (pllink_veth0->parent, ==, ifindex_veth1);
|
||||
|
||||
|
||||
/* The following tests whether we have a workaround for kernel bug
|
||||
* https://bugzilla.redhat.com/show_bug.cgi?id=1285827 in place. */
|
||||
pllink_veth1 = nm_platform_link_get (NM_PLATFORM_GET, ifindex_veth1);
|
||||
g_assert (pllink_veth1);
|
||||
g_assert_cmpint (pllink_veth1->parent, ==, ifindex_veth0);
|
||||
|
||||
|
||||
/* move one veth peer to another namespace and check that the
|
||||
* parent/IFLA_LINK of the remaining peer properly updates
|
||||
* (https://bugzilla.redhat.com/show_bug.cgi?id=1262908). */
|
||||
ns_handle = nmtstp_namespace_create (CLONE_NEWNET, &error);
|
||||
g_assert_no_error (error);
|
||||
g_assert (ns_handle);
|
||||
|
||||
nmtstp_run_command_check ("ip link set %s netns %ld", IFACE_VETH1, (long) nmtstp_namespace_handle_get_pid (ns_handle));
|
||||
NMTST_WAIT_ASSERT (100, {
|
||||
nmtstp_wait_for_signal (50);
|
||||
nm_platform_process_events (NM_PLATFORM_GET);
|
||||
|
||||
pllink_veth1 = nm_platform_link_get (NM_PLATFORM_GET, ifindex_veth1);
|
||||
pllink_veth0 = nm_platform_link_get (NM_PLATFORM_GET, ifindex_veth0);
|
||||
if ( !pllink_veth1
|
||||
&& pllink_veth0
|
||||
&& pllink_veth0->parent == NM_PLATFORM_LINK_OTHER_NETNS) {
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
out:
|
||||
nm_platform_link_delete (NM_PLATFORM_GET, ifindex_veth0);
|
||||
nm_platform_link_delete (NM_PLATFORM_GET, ifindex_veth1);
|
||||
nmtstp_namespace_handle_release (ns_handle);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
test_nl_bugs_spuroius_newlink (void)
|
||||
{
|
||||
const char *IFACE_BOND0 = "nm-test-bond0";
|
||||
const char *IFACE_DUMMY0 = "nm-test-dummy0";
|
||||
int ifindex_bond0, ifindex_dummy0;
|
||||
const NMPlatformLink *pllink;
|
||||
gboolean wait_for_settle;
|
||||
|
||||
/* see https://bugzilla.redhat.com/show_bug.cgi?id=1285719 */
|
||||
|
||||
nmtstp_run_command_check ("ip link add %s type dummy", IFACE_DUMMY0);
|
||||
ifindex_dummy0 = nmtstp_assert_wait_for_link (IFACE_DUMMY0, NM_LINK_TYPE_DUMMY, 100)->ifindex;
|
||||
|
||||
nmtstp_run_command_check ("ip link add %s type bond", IFACE_BOND0);
|
||||
ifindex_bond0 = nmtstp_assert_wait_for_link (IFACE_BOND0, NM_LINK_TYPE_BOND, 100)->ifindex;
|
||||
|
||||
nmtstp_link_set_updown (-1, ifindex_bond0, TRUE);
|
||||
|
||||
nmtstp_run_command_check ("ip link set %s master %s", IFACE_DUMMY0, IFACE_BOND0);
|
||||
NMTST_WAIT_ASSERT (100, {
|
||||
nmtstp_wait_for_signal (50);
|
||||
|
||||
pllink = nm_platform_link_get (NM_PLATFORM_GET, ifindex_dummy0);
|
||||
g_assert (pllink);
|
||||
if (pllink->master == ifindex_bond0)
|
||||
break;
|
||||
});
|
||||
|
||||
nmtstp_run_command_check ("ip link del %s", IFACE_BOND0);
|
||||
|
||||
wait_for_settle = TRUE;
|
||||
nmtstp_wait_for_signal (50);
|
||||
again:
|
||||
nm_platform_process_events (NM_PLATFORM_GET);
|
||||
pllink = nm_platform_link_get (NM_PLATFORM_GET, ifindex_bond0);
|
||||
g_assert (!pllink);
|
||||
|
||||
if (wait_for_settle) {
|
||||
wait_for_settle = FALSE;
|
||||
NMTST_WAIT (300, { nmtstp_wait_for_signal (50); });
|
||||
goto again;
|
||||
}
|
||||
|
||||
nm_platform_link_delete (NM_PLATFORM_GET, ifindex_bond0);
|
||||
nm_platform_link_delete (NM_PLATFORM_GET, ifindex_dummy0);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
test_nl_bugs_spuroius_dellink (void)
|
||||
{
|
||||
const char *IFACE_BRIDGE0 = "nm-test-bridge0";
|
||||
const char *IFACE_DUMMY0 = "nm-test-dummy0";
|
||||
int ifindex_bridge0, ifindex_dummy0;
|
||||
const NMPlatformLink *pllink;
|
||||
gboolean wait_for_settle;
|
||||
|
||||
/* see https://bugzilla.redhat.com/show_bug.cgi?id=1285719 */
|
||||
|
||||
nmtstp_run_command_check ("ip link add %s type dummy", IFACE_DUMMY0);
|
||||
ifindex_dummy0 = nmtstp_assert_wait_for_link (IFACE_DUMMY0, NM_LINK_TYPE_DUMMY, 100)->ifindex;
|
||||
|
||||
nmtstp_run_command_check ("ip link add %s type bridge", IFACE_BRIDGE0);
|
||||
ifindex_bridge0 = nmtstp_assert_wait_for_link (IFACE_BRIDGE0, NM_LINK_TYPE_BRIDGE, 100)->ifindex;
|
||||
|
||||
nmtstp_link_set_updown (-1, ifindex_bridge0, TRUE);
|
||||
|
||||
nmtstp_run_command_check ("ip link set %s master %s", IFACE_DUMMY0, IFACE_BRIDGE0);
|
||||
NMTST_WAIT_ASSERT (100, {
|
||||
nmtstp_wait_for_signal (50);
|
||||
|
||||
pllink = nm_platform_link_get (NM_PLATFORM_GET, ifindex_dummy0);
|
||||
g_assert (pllink);
|
||||
if (pllink->master == ifindex_bridge0)
|
||||
break;
|
||||
});
|
||||
|
||||
nm_platform_process_events (NM_PLATFORM_GET);
|
||||
|
||||
nmtstp_run_command_check ("ip link set %s nomaster", IFACE_DUMMY0);
|
||||
|
||||
wait_for_settle = TRUE;
|
||||
nmtstp_wait_for_signal (50);
|
||||
again:
|
||||
nm_platform_process_events (NM_PLATFORM_GET);
|
||||
pllink = nm_platform_link_get (NM_PLATFORM_GET, ifindex_bridge0);
|
||||
g_assert (pllink);
|
||||
pllink = nm_platform_link_get (NM_PLATFORM_GET, ifindex_dummy0);
|
||||
g_assert (pllink);
|
||||
g_assert_cmpint (pllink->parent, ==, 0);
|
||||
|
||||
if (wait_for_settle) {
|
||||
wait_for_settle = FALSE;
|
||||
NMTST_WAIT (300, { nmtstp_wait_for_signal (50); });
|
||||
goto again;
|
||||
}
|
||||
|
||||
nm_platform_link_delete (NM_PLATFORM_GET, ifindex_bridge0);
|
||||
nm_platform_link_delete (NM_PLATFORM_GET, ifindex_dummy0);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void
|
||||
init_tests (int *argc, char ***argv)
|
||||
{
|
||||
|
|
@ -1406,5 +1585,9 @@ setup_tests (void)
|
|||
test_software_detect_add ("/link/software/detect/vxlan/1", NM_LINK_TYPE_VXLAN, 1);
|
||||
|
||||
g_test_add_func ("/link/software/vlan/set-xgress", test_vlan_set_xgress);
|
||||
|
||||
g_test_add_func ("/link/nl-bugs/veth", test_nl_bugs_veth);
|
||||
g_test_add_func ("/link/nl-bugs/spurious-newlink", test_nl_bugs_spuroius_newlink);
|
||||
g_test_add_func ("/link/nl-bugs/spurious-dellink", test_nl_bugs_spuroius_dellink);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
#define DEVICE_NAME "nm-test-device"
|
||||
|
||||
static void
|
||||
ip4_route_callback (NMPlatform *platform, NMPObjectType obj_type, int ifindex, const NMPlatformIP4Route *received, NMPlatformSignalChangeType change_type, NMPlatformReason reason, SignalData *data)
|
||||
ip4_route_callback (NMPlatform *platform, NMPObjectType obj_type, int ifindex, const NMPlatformIP4Route *received, NMPlatformSignalChangeType change_type, SignalData *data)
|
||||
{
|
||||
g_assert (received);
|
||||
g_assert_cmpint (received->ifindex, ==, ifindex);
|
||||
|
|
@ -29,7 +29,7 @@ ip4_route_callback (NMPlatform *platform, NMPObjectType obj_type, int ifindex, c
|
|||
}
|
||||
|
||||
static void
|
||||
ip6_route_callback (NMPlatform *platform, NMPObjectType obj_type, int ifindex, const NMPlatformIP6Route *received, NMPlatformSignalChangeType change_type, NMPlatformReason reason, SignalData *data)
|
||||
ip6_route_callback (NMPlatform *platform, NMPObjectType obj_type, int ifindex, const NMPlatformIP6Route *received, NMPlatformSignalChangeType change_type, SignalData *data)
|
||||
{
|
||||
g_assert (received);
|
||||
g_assert_cmpint (received->ifindex, ==, ifindex);
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ devtimeout_ready (gpointer user_data)
|
|||
|
||||
static void
|
||||
link_changed (NMPlatform *platform, NMPObjectType *obj_type, int ifindex, const NMPlatformLink *link,
|
||||
NMPlatformSignalChangeType change_type, NMPlatformReason reason,
|
||||
NMPlatformSignalChangeType change_type,
|
||||
NMConnection *self)
|
||||
{
|
||||
NMIfcfgConnectionPrivate *priv = NM_IFCFG_CONNECTION_GET_PRIVATE (self);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue