mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2025-12-26 07:40:08 +01:00
NM_SHUTDOWN_TIMEOUT_MAX_MSEC is the maximum timeout for how long any async operation may take. The idea is that during shutdown of NetworkManager we give that much time to tear down. Then async operations may either implement cancellation or not bother with that. But in any case, they must complete within NM_SHUTDOWN_TIMEOUT_MAX_MSEC. Actually, for the time being, this has no effect at all. I am talking about the future here. See "Improve Shutdown of NetworkManager" in TODO. This patch is preparation for that effort. Anyway. Stopping pppd can take a longer time (5 seconds). That is currently the (known) longest time how long any of our async operations is allowed to take. As all async operations must complete before NM_SHUTDOWN_TIMEOUT_MAX_MSEC, and we want to wait at least 5 seconds for pppd, we need to increase the wait time NM_SHUTDOWN_TIMEOUT_MAX_MSEC. Also add and use NM_SHUTDOWN_TIMEOUT_5000_MSEC, which serves a similar purpose as NM_SHUTDOWN_TIMEOUT_1500_MSEC.
308 lines
14 KiB
C
308 lines
14 KiB
C
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
/*
|
|
* Copyright (C) 2004 - 2016 Red Hat, Inc.
|
|
* Copyright (C) 2005 - 2008 Novell, Inc.
|
|
*/
|
|
|
|
#ifndef __NETWORKMANAGER_UTILS_H__
|
|
#define __NETWORKMANAGER_UTILS_H__
|
|
|
|
#include "nm-core-utils.h"
|
|
#include "libnm-glib-aux/nm-dedup-multi.h"
|
|
#include "nm-setting-ip-config.h"
|
|
#include "nm-setting-ip6-config.h"
|
|
#include "libnm-platform/nm-platform.h"
|
|
|
|
/*****************************************************************************/
|
|
|
|
const char *nm_utils_get_ip_config_method(NMConnection *connection, int addr_family);
|
|
|
|
const char *nm_utils_get_shared_wifi_permission(NMConnection *connection);
|
|
|
|
void nm_utils_ppp_ip_methods_enabled(NMConnection *connection,
|
|
gboolean *out_ip4_enabled,
|
|
gboolean *out_ip6_enabled);
|
|
|
|
void _nm_utils_complete_generic_with_params(NMPlatform *platform,
|
|
NMConnection *connection,
|
|
const char *ctype,
|
|
NMConnection *const *existing_connections,
|
|
const char *preferred_id,
|
|
const char *fallback_id_prefix,
|
|
const char *ifname_prefix,
|
|
const char *ifname,
|
|
...) G_GNUC_NULL_TERMINATED;
|
|
|
|
#define nm_utils_complete_generic_with_params(platform, \
|
|
connection, \
|
|
ctype, \
|
|
existing_connections, \
|
|
preferred_id, \
|
|
fallback_id_prefix, \
|
|
ifname_prefix, \
|
|
ifname, \
|
|
...) \
|
|
_nm_utils_complete_generic_with_params(platform, \
|
|
connection, \
|
|
ctype, \
|
|
existing_connections, \
|
|
preferred_id, \
|
|
fallback_id_prefix, \
|
|
ifname_prefix, \
|
|
ifname, \
|
|
##__VA_ARGS__, \
|
|
NULL)
|
|
|
|
static inline void
|
|
nm_utils_complete_generic(NMPlatform *platform,
|
|
NMConnection *connection,
|
|
const char *ctype,
|
|
NMConnection *const *existing_connections,
|
|
const char *preferred_id,
|
|
const char *fallback_id_prefix,
|
|
const char *ifname_prefix,
|
|
const char *ifname,
|
|
gboolean default_enable_ipv6)
|
|
{
|
|
nm_utils_complete_generic_with_params(platform,
|
|
connection,
|
|
ctype,
|
|
existing_connections,
|
|
preferred_id,
|
|
fallback_id_prefix,
|
|
ifname_prefix,
|
|
ifname,
|
|
NM_CONNECTION_NORMALIZE_PARAM_IP6_CONFIG_METHOD,
|
|
default_enable_ipv6
|
|
? NM_SETTING_IP6_CONFIG_METHOD_AUTO
|
|
: NM_SETTING_IP6_CONFIG_METHOD_IGNORE);
|
|
}
|
|
|
|
typedef gboolean(NMUtilsMatchFilterFunc)(NMConnection *connection, gpointer user_data);
|
|
|
|
NMConnection *nm_utils_match_connection(NMConnection *const *connections,
|
|
NMConnection *original,
|
|
gboolean indicated,
|
|
gboolean device_has_carrier,
|
|
gint64 default_v4_metric,
|
|
gint64 default_v6_metric,
|
|
NMUtilsMatchFilterFunc match_filter_func,
|
|
gpointer match_filter_data);
|
|
|
|
int nm_match_spec_device_by_pllink(const NMPlatformLink *pllink,
|
|
const char *match_device_type,
|
|
const char *match_dhcp_plugin,
|
|
const GSList *specs,
|
|
int no_match_value);
|
|
|
|
/*****************************************************************************/
|
|
|
|
NMPlatformRoutingRule *nm_ip_routing_rule_to_platform(const NMIPRoutingRule *rule,
|
|
NMPlatformRoutingRule *out_pl);
|
|
|
|
/*****************************************************************************/
|
|
|
|
/* during shutdown, there are two relevant timeouts. One is
|
|
* NM_SHUTDOWN_TIMEOUT_MAX_MSEC which is plenty of time, that we give for all
|
|
* actions to complete. Of course, during shutdown components should hurry
|
|
* to cleanup.
|
|
*
|
|
* When we initiate shutdown, we should start killing child processes
|
|
* with SIGTERM. If they don't complete within NM_SHUTDOWN_TIMEOUT_MAX_MSEC, we send
|
|
* SIGKILL.
|
|
*
|
|
* After NM_SHUTDOWN_TIMEOUT_MAX_MSEC, NetworkManager will however not yet terminate right
|
|
* away. It iterates the mainloop for another NM_SHUTDOWN_TIMEOUT_ADDITIONAL_MSEC. This
|
|
* should give time to reap the child process (after SIGKILL).
|
|
*
|
|
* So, the maximum time we should wait before sending SIGKILL should be at most
|
|
* NM_SHUTDOWN_TIMEOUT_MAX_MSEC.
|
|
*/
|
|
#define NM_SHUTDOWN_TIMEOUT_MAX_MSEC 5000
|
|
#define NM_SHUTDOWN_TIMEOUT_ADDITIONAL_MSEC 500
|
|
|
|
/**
|
|
* NM_SHUTDOWN_TIMEOUT_1500_MSEC: this is just 1500 msec. The special
|
|
* thing about the define is that you are guaranteed that this is not
|
|
* longer than NM_SHUTDOWN_TIMEOUT_MAX_MSEC.
|
|
* When you perform an async operation, it must either be cancellable
|
|
* (and complete fast) or never take longer than NM_SHUTDOWN_TIMEOUT_MAX_MSEC.
|
|
* The usage of this macro makes that relation to NM_SHUTDOWN_TIMEOUT_MAX_MSEC
|
|
* explicit.
|
|
*/
|
|
#define NM_SHUTDOWN_TIMEOUT_1500_MSEC 1500
|
|
|
|
/* See NM_SHUTDOWN_TIMEOUT_1500_MSEC. */
|
|
#define NM_SHUTDOWN_TIMEOUT_5000_MSEC 5000
|
|
|
|
typedef enum {
|
|
/* There is no watched_obj argument, and the shutdown is delayed until the user
|
|
* explicitly calls unregister on the returned handle. */
|
|
NM_SHUTDOWN_WAIT_TYPE_HANDLE,
|
|
|
|
/* The watched_obj argument is a GObject, and shutdown is delayed until the object
|
|
* gets destroyed (or unregistered). */
|
|
NM_SHUTDOWN_WAIT_TYPE_OBJECT,
|
|
|
|
/* The watched_obj argument is a GCancellable, and shutdown is delayed until the object
|
|
* gets destroyed (or unregistered). Note that after NM_SHUTDOWN_TIMEOUT_MAX_MSEC, the
|
|
* cancellable will be cancelled to notify listeners about the shutdown. */
|
|
NM_SHUTDOWN_WAIT_TYPE_CANCELLABLE,
|
|
} NMShutdownWaitType;
|
|
|
|
typedef struct _NMShutdownWaitObjHandle NMShutdownWaitObjHandle;
|
|
|
|
NMShutdownWaitObjHandle *nm_shutdown_wait_obj_register_full(gpointer watched_obj,
|
|
NMShutdownWaitType wait_type,
|
|
char *msg_reason,
|
|
gboolean free_msg_reason);
|
|
|
|
static inline NMShutdownWaitObjHandle *
|
|
nm_shutdown_wait_obj_register_object_full(gpointer watched_obj,
|
|
char *msg_reason,
|
|
gboolean free_msg_reason)
|
|
{
|
|
return nm_shutdown_wait_obj_register_full(watched_obj,
|
|
NM_SHUTDOWN_WAIT_TYPE_OBJECT,
|
|
msg_reason,
|
|
free_msg_reason);
|
|
}
|
|
|
|
#define nm_shutdown_wait_obj_register_object(watched_obj, msg_reason) \
|
|
nm_shutdown_wait_obj_register_object_full((watched_obj), ("" msg_reason ""), FALSE)
|
|
|
|
static inline NMShutdownWaitObjHandle *
|
|
nm_shutdown_wait_obj_register_handle_full(char *msg_reason, gboolean free_msg_reason)
|
|
{
|
|
return nm_shutdown_wait_obj_register_full(NULL,
|
|
NM_SHUTDOWN_WAIT_TYPE_HANDLE,
|
|
msg_reason,
|
|
free_msg_reason);
|
|
}
|
|
|
|
#define nm_shutdown_wait_obj_register_handle(msg_reason) \
|
|
nm_shutdown_wait_obj_register_handle_full(("" msg_reason ""), FALSE)
|
|
|
|
static inline NMShutdownWaitObjHandle *
|
|
nm_shutdown_wait_obj_register_cancellable_full(GCancellable *watched_obj,
|
|
char *msg_reason,
|
|
gboolean free_msg_reason)
|
|
{
|
|
return nm_shutdown_wait_obj_register_full(watched_obj,
|
|
NM_SHUTDOWN_WAIT_TYPE_CANCELLABLE,
|
|
msg_reason,
|
|
free_msg_reason);
|
|
}
|
|
|
|
#define nm_shutdown_wait_obj_register_cancellable(watched_obj, msg_reason) \
|
|
nm_shutdown_wait_obj_register_cancellable_full((watched_obj), ("" msg_reason ""), FALSE)
|
|
|
|
void nm_shutdown_wait_obj_unregister(NMShutdownWaitObjHandle *handle);
|
|
|
|
/*****************************************************************************/
|
|
|
|
const char *nm_utils_file_is_in_path(const char *abs_filename, const char *abs_path);
|
|
|
|
/*****************************************************************************/
|
|
|
|
GPtrArray *
|
|
nm_utils_qdiscs_from_tc_setting(NMPlatform *platform, NMSettingTCConfig *s_tc, int ip_ifindex);
|
|
GPtrArray *
|
|
nm_utils_tfilters_from_tc_setting(NMPlatform *platform, NMSettingTCConfig *s_tc, int ip_ifindex);
|
|
|
|
void nm_utils_ip_route_attribute_to_platform(int addr_family,
|
|
NMIPRoute *s_route,
|
|
NMPlatformIPRoute *r,
|
|
gint64 route_table);
|
|
|
|
void nm_utils_ip_addresses_to_dbus(int addr_family,
|
|
const NMDedupMultiHeadEntry *head_entry,
|
|
const NMPObject *best_default_route,
|
|
GVariant **out_address_data,
|
|
GVariant **out_addresses);
|
|
|
|
void nm_utils_ip_routes_to_dbus(int addr_family,
|
|
const NMDedupMultiHeadEntry *head_entry,
|
|
GVariant **out_route_data,
|
|
GVariant **out_routes);
|
|
|
|
/*****************************************************************************/
|
|
|
|
/* For now, all we track about a DHCP lease is the GHashTable with
|
|
* the options.
|
|
*
|
|
* We don't add a separate type for that, but we also don't want to use
|
|
* GHashTable directly (because most importantly leases should be immutable
|
|
* and passing a GHashTable pointer around neither makes it clear that
|
|
* this is a lease nor that it's immutable.
|
|
*
|
|
* Instead, add a simple opaque pointer and accessors that cast to a GHashTable.
|
|
*
|
|
* It has no overhead at run time, but gives some rudimentary type safety. */
|
|
|
|
typedef struct _NMDhcpLease NMDhcpLease;
|
|
|
|
static inline NMDhcpLease *
|
|
nm_dhcp_lease_new_from_options(GHashTable *options_take)
|
|
{
|
|
/* a NMDhcpLease is really just a GHashTable. But it's also supposed to be *immutable*.
|
|
*
|
|
* Hence, the API here takes over ownership of the reference to @options_take, that
|
|
* is to emphasize that we acquire ownership of the hash, and it should not be modified
|
|
* anymore. */
|
|
return (NMDhcpLease *) options_take;
|
|
}
|
|
|
|
static inline GHashTable *
|
|
nm_dhcp_lease_get_options(NMDhcpLease *lease)
|
|
{
|
|
return (GHashTable *) lease;
|
|
}
|
|
|
|
static inline NMDhcpLease *
|
|
nm_dhcp_lease_ref(NMDhcpLease *lease)
|
|
{
|
|
if (lease)
|
|
g_hash_table_ref((GHashTable *) lease);
|
|
return lease;
|
|
}
|
|
|
|
static inline NMDhcpLease *
|
|
nm_dhcp_lease_unref(NMDhcpLease *lease)
|
|
{
|
|
if (lease)
|
|
g_hash_table_unref((GHashTable *) lease);
|
|
return NULL;
|
|
}
|
|
|
|
static inline const char *
|
|
nm_dhcp_lease_lookup_option(NMDhcpLease *lease, const char *option)
|
|
{
|
|
nm_assert(option);
|
|
|
|
return nm_g_hash_table_lookup((GHashTable *) lease, option);
|
|
}
|
|
|
|
NM_AUTO_DEFINE_FCN(NMDhcpLease *, _nm_auto_unref_dhcplease, nm_dhcp_lease_unref);
|
|
#define nm_auto_unref_dhcplease nm_auto(_nm_auto_unref_dhcplease)
|
|
|
|
/*****************************************************************************/
|
|
|
|
NMSetting *nm_utils_platform_capture_ip_setting(NMPlatform *platform,
|
|
int addr_family,
|
|
int ifindex,
|
|
gboolean maybe_ipv6_disabled);
|
|
|
|
/*****************************************************************************/
|
|
|
|
void nm_platform_setup(NMPlatform *instance);
|
|
NMPlatform *nm_platform_get(void);
|
|
|
|
#define NM_PLATFORM_GET (nm_platform_get())
|
|
|
|
void nm_linux_platform_setup(void);
|
|
void nm_linux_platform_setup_with_tc_cache(void);
|
|
|
|
/*****************************************************************************/
|
|
|
|
#endif /* __NETWORKMANAGER_UTILS_H__ */
|