diff --git a/include/nm-test-utils.h b/include/nm-test-utils.h index 9fc6fad618..43d5604cab 100644 --- a/include/nm-test-utils.h +++ b/include/nm-test-utils.h @@ -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=")]); diff --git a/src/devices/adsl/nm-device-adsl.c b/src/devices/adsl/nm-device-adsl.c index 08a7511abe..4705b398ab 100644 --- a/src/devices/adsl/nm-device-adsl.c +++ b/src/devices/adsl/nm-device-adsl.c @@ -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); diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 07b7b072bf..6a78ed4b1a 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -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; diff --git a/src/nm-default-route-manager.c b/src/nm-default-route-manager.c index 68ef032e95..c3b258a2f1 100644 --- a/src/nm-default-route-manager.c +++ b/src/nm-default-route-manager.c @@ -1359,7 +1359,6 @@ _platform_changed_cb (NMPlatform *platform, int ifindex, gpointer platform_object, NMPlatformSignalChangeType change_type, - NMPlatformReason reason, NMDefaultRouteManager *self) { switch (obj_type) { diff --git a/src/nm-iface-helper.c b/src/nm-iface-helper.c index ee9c243af9..fbe4c69885 100644 --- a/src/nm-iface-helper.c +++ b/src/nm-iface-helper.c @@ -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) diff --git a/src/nm-manager.c b/src/nm-manager.c index bb92a13f38..72d9144d84 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -1965,7 +1965,6 @@ platform_link_cb (NMPlatform *platform, int ifindex, NMPlatformLink *plink, NMPlatformSignalChangeType change_type, - NMPlatformReason reason, gpointer user_data) { PlatformLinkCbData *data; diff --git a/src/nm-route-manager.c b/src/nm-route-manager.c index f2ab073bd9..18781c6918 100644 --- a/src/nm-route-manager.c +++ b/src/nm-route-manager.c @@ -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; diff --git a/src/platform/nm-fake-platform.c b/src/platform/nm-fake-platform.c index a32c909937..973df29a6e 100644 --- a/src/platform/nm-fake-platform.c +++ b/src/platform/nm-fake-platform.c @@ -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; } diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index b7506e7d1c..b79aa76767 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -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); } diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index 6988d1a5f4..bb82ab0959 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -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); } diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h index e64a9bf9e0..00029b3aeb 100644 --- a/src/platform/nm-platform.h +++ b/src/platform/nm-platform.h @@ -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, diff --git a/src/platform/nmp-object.c b/src/platform/nmp-object.c index 2264c9cd62..ef467f4241 100644 --- a/src/platform/nmp-object.c +++ b/src/platform/nmp-object.c @@ -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, diff --git a/src/platform/nmp-object.h b/src/platform/nmp-object.h index 7de44895e6..971bd37eca 100644 --- a/src/platform/nmp-object.h +++ b/src/platform/nmp-object.h @@ -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; diff --git a/src/platform/tests/Makefile.am b/src/platform/tests/Makefile.am index bc6ec39e20..5996f34706 100644 --- a/src/platform/tests/Makefile.am +++ b/src/platform/tests/Makefile.am @@ -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) \ diff --git a/src/platform/tests/platform.c b/src/platform/tests/platform.c deleted file mode 100644 index 33ef8928dc..0000000000 --- a/src/platform/tests/platform.c +++ /dev/null @@ -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 -#include -#include -#include -#include - -#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, " " }, - { "sysctl-get", "get /proc/sys or /sys value", do_sysctl_get, 1, "" }, - { "link-get-all", "print all links", do_link_get_all, 0, "" }, - { "dummy-add", "add dummy interface", do_dummy_add, 1, "" }, - { "bridge-add", "add bridge interface", do_bridge_add, 1, "" }, - { "bond-add", "add bond interface", do_bond_add, 1, "" }, - { "team-add", "add team interface", do_team_add, 1, "" }, - { "vlan-add", "add vlan interface", do_vlan_add, 4, " " }, - { "link-exists", "check ifname for existance", do_link_exists, 1, "" }, - { "link-delete", "delete interface", do_link_delete, 1, "" }, - { "link-get-ifindex>", "get interface index", do_link_get_ifindex, 1, "" }, - { "link-get-name", "get interface name", do_link_get_name, 1, "" }, - { "link-get-type", "get interface type", do_link_get_type, 1, "" }, - { "link-is-software", "check if interface is a software one", do_link_is_software, 1, "" }, - { "link-supports-slaves", "check if interface supports slaves", do_link_supports_slaves, 1, "" }, - { "link-set-up", "set interface up", do_link_set_up, 1, "" }, - { "link-set-down", "set interface down", do_link_set_down, 1, "" }, - { "link-set-arp", "activate interface arp", do_link_set_arp, 1, "" }, - { "link-set-noarp", "deactivate interface arp", do_link_set_noarp, 1, "" }, - { "link-is-up", "check if interface is up", do_link_is_up, 1, "" }, - { "link-is-connected", "check interface carrier", do_link_is_connected, 1, "" }, - { "link-uses-arp", "check whether interface uses arp", do_link_uses_arp, 1, "" }, - { "link-get-address", "print link address", do_link_get_address, 1, "" }, - { "link-set-address", "set link address", do_link_set_address, 2, " " }, - { "link-get-mtu", "print link mtu", do_link_get_mtu, 1, "" }, - { "link-set-mtu", "set link mtu", do_link_set_mtu, 2, " " }, - { "link-supports-carrier-detect", "check whether interface supports carrier detect", - do_link_supports_carrier_detect, 1, "" }, - { "link-supports-vlans", "check whether interface supports VLANs", - do_link_supports_vlans, 1, "" }, - { "link-enslave", "enslave slave interface with master", do_link_enslave, 2, " " }, - { "link-release", "release save interface from master", do_link_release, 2, " " }, - { "link-get-master", "print master interface of a slave", do_link_get_master, 1, "" }, - { "link-master-set-option", "set master option", do_master_set_option, 3, - "