diff options
| author | Michael Biebl <biebl@debian.org> | 2025-11-17 17:43:34 +0100 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2025-11-17 17:43:34 +0100 |
| commit | 01609e485803fa250413385ae209660fb7b30a2e (patch) | |
| tree | 0992589c495fcaaea35f4a0452362326a4dbc3ba /src/core | |
| parent | bc5f10851bffd6af1c2855635be7a28b6dba3195 (diff) | |
New upstream version 1.54.2 upstream/1.54.2
Diffstat (limited to 'src/core')
| -rw-r--r-- | src/core/devices/nm-device-hsr.c | 36 | ||||
| -rw-r--r-- | src/core/devices/nm-device-utils.c | 6 | ||||
| -rw-r--r-- | src/core/devices/nm-device.c | 265 | ||||
| -rw-r--r-- | src/core/devices/nm-device.h | 23 | ||||
| -rw-r--r-- | src/core/devices/ovs/nm-ovsdb.c | 32 | ||||
| -rw-r--r-- | src/core/nm-manager.c | 110 | ||||
| -rw-r--r-- | src/core/nm-manager.h | 4 | ||||
| -rw-r--r-- | src/core/nm-policy.c | 97 |
8 files changed, 349 insertions, 224 deletions
diff --git a/src/core/devices/nm-device-hsr.c b/src/core/devices/nm-device-hsr.c index 59454ee3..e3368a5b 100644 --- a/src/core/devices/nm-device-hsr.c +++ b/src/core/devices/nm-device-hsr.c @@ -116,29 +116,51 @@ create_and_realize(NMDevice *device, const NMPlatformLink **out_plink, GError **error) { - const char *iface = nm_device_get_iface(device); - NMSettingHsr *s_hsr; - NMPlatformLnkHsr lnk = {}; - int r; + const char *iface = nm_device_get_iface(device); + nm_auto_free char *err_msg = NULL; + NMSettingHsr *s_hsr; + NMPlatformLnkHsr lnk = {}; + int r = 0; s_hsr = _nm_connection_get_setting(connection, NM_TYPE_SETTING_HSR); + nm_assert(s_hsr); if (nm_setting_hsr_get_port1(s_hsr) != NULL) lnk.port1 = nm_platform_link_get_ifindex(NM_PLATFORM_GET, nm_setting_hsr_get_port1(s_hsr)); if (nm_setting_hsr_get_port2(s_hsr) != NULL) lnk.port2 = nm_platform_link_get_ifindex(NM_PLATFORM_GET, nm_setting_hsr_get_port2(s_hsr)); - lnk.multicast_spec = nm_setting_hsr_get_multicast_spec(s_hsr); - lnk.prp = nm_setting_hsr_get_prp(s_hsr); + if (nm_setting_hsr_get_interlink(s_hsr) != NULL) { + const char *ifname = nm_setting_hsr_get_interlink(s_hsr); + int ifindex = nm_platform_link_get_ifindex(NM_PLATFORM_GET, ifname); + + if (ifindex <= 0) { + err_msg = g_strdup_printf("interlink port '%s' does not exist", ifname); + goto out; + } + + lnk.interlink = ifindex; + } + + lnk.multicast_spec = nm_setting_hsr_get_multicast_spec(s_hsr); + lnk.prp = nm_setting_hsr_get_prp(s_hsr); + lnk.protocol_version = nm_setting_hsr_get_protocol_version(s_hsr); + r = nm_platform_link_hsr_add(nm_device_get_platform(device), iface, &lnk, out_plink); + if (r < 0) { + err_msg = g_strdup(nm_strerror(r) ?: "unknown"); + } + +out: + if (err_msg) { g_set_error(error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, "Failed to create HSR interface '%s' for '%s': %s", iface, nm_connection_get_id(connection), - nm_strerror(r)); + err_msg); return FALSE; } diff --git a/src/core/devices/nm-device-utils.c b/src/core/devices/nm-device-utils.c index 9fd7ac9d..a78499fb 100644 --- a/src/core/devices/nm-device-utils.c +++ b/src/core/devices/nm-device-utils.c @@ -135,13 +135,15 @@ NM_UTILS_LOOKUP_STR_DEFINE( NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_UNMANAGED_LINK_NOT_INIT, "unmanaged-link-not-init"), NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_UNMANAGED_QUITTING, "unmanaged-quitting"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_UNMANAGED_SLEEPING, "unmanaged-sleeping"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_UNMANAGED_MANAGER_DISABLED, + "unmanaged-nm-disabled"), NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_UNMANAGED_USER_CONF, "unmanaged-user-conf"), NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_UNMANAGED_USER_EXPLICIT, "unmanaged-user-explicit"), NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_UNMANAGED_USER_SETTINGS, "unmanaged-user-settings"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_UNMANAGED_USER_UDEV, "unmanaged-user-udev"), ); + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_UNMANAGED_USER_UDEV, "unmanaged-user-udev"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_NETWORKING_OFF, "networking-off"), ); NM_UTILS_LOOKUP_STR_DEFINE(nm_device_mtu_source_to_string, NMDeviceMtuSource, diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c index 79b1076d..6bba982a 100644 --- a/src/core/devices/nm-device.c +++ b/src/core/devices/nm-device.c @@ -692,6 +692,8 @@ typedef struct _NMDevicePrivate { IPDevStateData ipdev_data_unspec; + gulong sharing_ipv4_changed_id; + struct { /* If we set the addrgenmode6, this records the previously set value. */ guint8 previous_mode_val; @@ -779,7 +781,6 @@ typedef struct _NMDevicePrivate { char *prop_ip_iface; /* IP interface D-Bus property */ GList *ping_operations; GSource *ping_timeout; - bool refresh_forwarding_done : 1; } NMDevicePrivate; G_DEFINE_ABSTRACT_TYPE(NMDevice, nm_device, NM_TYPE_DBUS_OBJECT) @@ -867,6 +868,8 @@ static void _dev_ipshared4_spawn_dnsmasq(NMDevice *self); static void _dev_ipshared6_start(NMDevice *self); +static void _dev_ipforwarding4_start(NMDevice *self, int addr_family); + static void _cleanup_ip_pre(NMDevice *self, int addr_family, CleanupType cleanup_type, gboolean preserve_dhcp); @@ -2131,8 +2134,8 @@ _prop_get_ipvx_dhcp_send_hostname(NMDevice *self, int addr_family) return send_hostname_v2; } -NMSettingIPConfigForwarding -nm_device_get_ipv4_forwarding(NMDevice *self) +static NMSettingIPConfigForwarding +_prop_get_ipv4_forwarding(NMDevice *self) { NMSettingIPConfig *s_ip; NMSettingIPConfigForwarding forwarding; @@ -3778,7 +3781,7 @@ nm_device_assume_state_reset(NMDevice *self) /*****************************************************************************/ -char * +static char * nm_device_sysctl_ip_conf_get(NMDevice *self, int addr_family, const char *property) { const char *ifname; @@ -6645,7 +6648,7 @@ concheck_update_state(NMDevice *self, } } -const char * +static const char * nm_device_get_effective_ip_config_method(NMDevice *self, int addr_family) { NMDeviceClass *klass; @@ -8639,6 +8642,8 @@ nm_device_unrealize(NMDevice *self, gboolean remove_resources, GError **error) g_object_thaw_notify(G_OBJECT(self)); + nm_device_managed_type_set(self, NM_DEVICE_MANAGED_TYPE_REMOVED); + nm_device_set_unmanaged_flags(self, NM_UNMANAGED_PLATFORM_INIT, TRUE); nm_device_set_unmanaged_flags(self, @@ -10394,6 +10399,43 @@ sriov_params_cb(GError *error, gpointer user_data) nm_device_activate_schedule_stage1_device_prepare(self, FALSE); } +static gboolean +sriov_gen_platform_vfs(NMDevice *self, + NMSettingSriov *s_sriov, + NMPlatformVF ***plat_vfs_out, + GError **error) +{ + nm_auto_freev NMPlatformVF **plat_vfs = NULL; + guint num; + + nm_assert(s_sriov); + nm_assert(plat_vfs_out && !*plat_vfs_out); + + num = nm_setting_sriov_get_num_vfs(s_sriov); + plat_vfs = g_new0(NMPlatformVF *, num + 1); + + for (int i = 0; i < num; i++) { + NMSriovVF *vf = nm_setting_sriov_get_vf(s_sriov, i); + gs_free_error GError *local = NULL; + + plat_vfs[i] = sriov_vf_config_to_platform(self, vf, &local); + + if (!plat_vfs[i]) { + g_set_error(error, + local->domain, + local->code, + "VF '%s' is invalid: %s", + nm_utils_sriov_vf_to_str(vf, FALSE, NULL), + local->message); + return FALSE; + } + } + + *plat_vfs_out = g_steal_pointer(&plat_vfs); + + return TRUE; +} + /* * activate_stage1_device_prepare * @@ -10440,10 +10482,7 @@ activate_stage1_device_prepare(NMDevice *self) if (s_sriov && nm_device_has_capability(self, NM_DEVICE_CAP_SRIOV)) { nm_auto_freev NMPlatformVF **plat_vfs = NULL; gs_free_error GError *error = NULL; - NMSriovVF *vf; NMTernary autoprobe; - guint num; - guint i; autoprobe = nm_setting_sriov_get_autoprobe_drivers(s_sriov); if (autoprobe == NM_TERNARY_DEFAULT) { @@ -10456,21 +10495,12 @@ activate_stage1_device_prepare(NMDevice *self) NM_OPTION_BOOL_TRUE); } - num = nm_setting_sriov_get_num_vfs(s_sriov); - plat_vfs = g_new0(NMPlatformVF *, num + 1); - for (i = 0; i < num; i++) { - vf = nm_setting_sriov_get_vf(s_sriov, i); - plat_vfs[i] = sriov_vf_config_to_platform(self, vf, &error); - if (!plat_vfs[i]) { - _LOGE(LOGD_DEVICE, - "failed to apply SR-IOV VF '%s': %s", - nm_utils_sriov_vf_to_str(vf, FALSE, NULL), - error->message); - nm_device_state_changed(self, - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_SRIOV_CONFIGURATION_FAILED); - return; - } + if (!sriov_gen_platform_vfs(self, s_sriov, &plat_vfs, &error)) { + _LOGE(LOGD_DEVICE, "cannot parse the VF list: %s", error->message); + nm_device_state_changed(self, + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_SRIOV_CONFIGURATION_FAILED); + return; } /* When changing the number of VFs the kernel can block @@ -13139,17 +13169,12 @@ activate_stage3_ip_config_for_addr_family(NMDevice *self, int addr_family) goto out_devip; if (IS_IPv4) { - NMSettingIPConfigForwarding ipv4_forwarding = nm_device_get_ipv4_forwarding(self); - - if (NM_IN_SET(ipv4_forwarding, - NM_SETTING_IP_CONFIG_FORWARDING_NO, - NM_SETTING_IP_CONFIG_FORWARDING_YES)) { - nm_device_sysctl_ip_conf_set(self, AF_INET, "forwarding", ipv4_forwarding ? "1" : "0"); - } priv->ipll_data_4.v4.mode = _prop_get_ipv4_link_local(self); if (priv->ipll_data_4.v4.mode == NM_SETTING_IP4_LL_ENABLED) _dev_ipll4_start(self); + _dev_ipforwarding4_start(self, addr_family); + if (nm_streq(priv->ipv4_method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) _dev_ipdhcpx_start(self, AF_INET); else if (nm_streq(priv->ipv4_method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL)) { @@ -13469,15 +13494,21 @@ nm_device_activate_schedule_stage3_ip_config(NMDevice *self, gboolean do_sync) static void _dev_ipsharedx_set_state(NMDevice *self, int addr_family, NMDeviceIPState state) { - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - const int IS_IPv4 = NM_IS_IPv4(addr_family); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + const int IS_IPv4 = NM_IS_IPv4(addr_family); + NMDeviceIPState old_state = priv->ipshared_data_x[IS_IPv4].state; - if (priv->ipshared_data_x[IS_IPv4].state != state) { + if (old_state != state) { _LOGD_ipshared(addr_family, "set state %s (was %s)", nm_device_ip_state_to_string(state), - nm_device_ip_state_to_string(priv->ipshared_data_x[IS_IPv4].state)); + nm_device_ip_state_to_string(old_state)); priv->ipshared_data_x[IS_IPv4].state = state; + + if (old_state == NM_DEVICE_IP_STATE_READY || state == NM_DEVICE_IP_STATE_READY) + nm_manager_update_shared_connection(NM_MANAGER_GET, + addr_family, + state == NM_DEVICE_IP_STATE_READY); } } @@ -13772,6 +13803,106 @@ _dev_ipshared6_start(NMDevice *self) /*****************************************************************************/ +/** + * Set the device's forwarding to the specified value. If %NM_TERNARY_DEFAULT is specified, + * it's set to the kernel's default, otherwise it's set to the specific value. + */ +static void +_dev_ipforwarding4_set(NMDevice *self, NMTernary val) +{ + gs_free const char *default_forwarding = NULL; + gs_free const char *current_forwarding = NULL; + const char *val_str; + + if (val != NM_TERNARY_DEFAULT) { + val_str = val ? "1" : "0"; + } else { + default_forwarding = nm_platform_sysctl_get( + nm_device_get_platform(self), + NMP_SYSCTL_PATHID_ABSOLUTE("/proc/sys/net/ipv4/conf/default/forwarding")); + + if (!default_forwarding) { + _LOGW(LOGD_DEVICE, + "error setting IPv4 forwarding: can't read default forwarding value: %s", + nm_strerror_native(errno)); + return; /* Non fatal */ + } + + val_str = default_forwarding; + } + + current_forwarding = nm_device_sysctl_ip_conf_get(self, AF_INET, "forwarding"); + if (nm_streq0(current_forwarding, val_str)) + return; + + if (!nm_device_sysctl_ip_conf_set(self, AF_INET, "forwarding", val_str)) + _LOGW(LOGD_DEVICE, + "error setting IPv4 forwarding to '%s': %s", + val_str, + nm_strerror_native(errno)); +} + +static void +_dev_ipforwarding4_auto_cb(NMManager *manager, gboolean sharing_ipv4, gpointer data) +{ + NMDevice *self = NM_DEVICE(data); + + _dev_ipforwarding4_set(self, sharing_ipv4 ? NM_TERNARY_TRUE : NM_TERNARY_DEFAULT); +} + +static void +_dev_ipforwarding4_start(NMDevice *self, int addr_family) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + NMSettingIPConfigForwarding ipv4_forwarding = _prop_get_ipv4_forwarding(self); + NMTernary new_forwarding = NM_TERNARY_DEFAULT; + + /* IPv6 per-interface forwarding not supported yet */ + if (addr_family != AF_INET) + return; + + if (nm_streq(priv->ipv4_method, NM_SETTING_IP4_CONFIG_METHOD_SHARED)) { + new_forwarding = NM_TERNARY_TRUE; + } else if (ipv4_forwarding == NM_SETTING_IP_CONFIG_FORWARDING_YES) { + new_forwarding = NM_TERNARY_TRUE; + } else if (ipv4_forwarding == NM_SETTING_IP_CONFIG_FORWARDING_NO) { + new_forwarding = NM_TERNARY_FALSE; + } else if (ipv4_forwarding == NM_SETTING_IP_CONFIG_FORWARDING_AUTO) { + if (nm_manager_get_sharing_ipv4(NM_MANAGER_GET)) + new_forwarding = NM_TERNARY_TRUE; + else + new_forwarding = NM_TERNARY_DEFAULT; + + if (!priv->sharing_ipv4_changed_id) + priv->sharing_ipv4_changed_id = g_signal_connect(NM_MANAGER_GET, + NM_MANAGER_SHARING_IPV4_CHANGED, + G_CALLBACK(_dev_ipforwarding4_auto_cb), + self); + } else { + nm_assert_not_reached(); + } + + _dev_ipforwarding4_set(self, new_forwarding); +} + +static void +_dev_ipforwarding_cleanup(NMDevice *self, int addr_family, CleanupType cleanup_type) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + + if (!NM_IS_IPv4(addr_family)) + return; + + nm_clear_g_signal_handler(NM_MANAGER_GET, &priv->sharing_ipv4_changed_id); + + if (NM_IN_SET(cleanup_type, CLEANUP_TYPE_DECONFIGURE, CLEANUP_TYPE_KEEP_REAPPLY)) { + /* Deconfigure by restoring kernel's default */ + _dev_ipforwarding4_set(self, NM_TERNARY_DEFAULT); + } +} + +/*****************************************************************************/ + static void act_request_set(NMDevice *self, NMActRequest *act_request) { @@ -13884,6 +14015,8 @@ _cleanup_ip_pre(NMDevice *self, int addr_family, CleanupType cleanup_type, gbool NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); gboolean keep_reapply = (cleanup_type == CLEANUP_TYPE_KEEP_REAPPLY); + _dev_ipforwarding_cleanup(self, addr_family, cleanup_type); + _dev_ipsharedx_cleanup(self, addr_family); _dev_ipdev_cleanup(self, AF_UNSPEC); @@ -14066,7 +14199,8 @@ can_reapply_change(NMDevice *self, return nm_device_hash_check_invalid_keys(diffs, NM_SETTING_SRIOV_SETTING_NAME, error, - NM_SETTING_SRIOV_PRESERVE_ON_DOWN); + NM_SETTING_SRIOV_PRESERVE_ON_DOWN, + NM_SETTING_SRIOV_VFS); } out_fail: @@ -14244,9 +14378,35 @@ check_and_reapply_connection(NMDevice *self, nm_device_link_properties_set(self, TRUE); - if (priv->state >= NM_DEVICE_STATE_CONFIG) + if (priv->state >= NM_DEVICE_STATE_CONFIG) { + GHashTable *sriov_diff; + lldp_setup(self, NM_TERNARY_DEFAULT); + sriov_diff = nm_g_hash_table_lookup(diffs, NM_SETTING_SRIOV_SETTING_NAME); + + if (sriov_diff && nm_g_hash_table_lookup(sriov_diff, NM_SETTING_SRIOV_VFS)) { + nm_auto_freev NMPlatformVF **plat_vfs = NULL; + NMSettingSriov *s_sriov; + + s_sriov = (NMSettingSriov *) nm_connection_get_setting(applied, NM_TYPE_SETTING_SRIOV); + + if (s_sriov) { + gs_free_error GError *local = NULL; + + if (!sriov_gen_platform_vfs(self, s_sriov, &plat_vfs, &local) + || !nm_platform_link_set_sriov_vfs(nm_device_get_platform(self), + priv->ifindex, + (const NMPlatformVF *const *) plat_vfs)) { + _LOGE(LOGD_DEVICE, + "failed to reapply SRIOV VFs%s%s", + local ? ": " : "", + local ? local->message : ""); + } + } + } + } + if (priv->state >= NM_DEVICE_STATE_IP_CONFIG) { /* Allow reapply of MTU */ priv->mtu_source = NM_DEVICE_MTU_SOURCE_NONE; @@ -15613,7 +15773,7 @@ nm_device_get_firmware_missing(NMDevice *self) NM_UTILS_FLAGS2STR_DEFINE(nm_unmanaged_flags2str, NMUnmanagedFlags, - NM_UTILS_FLAGS2STR(NM_UNMANAGED_SLEEPING, "sleeping"), + NM_UTILS_FLAGS2STR(NM_UNMANAGED_MANAGER_DISABLED, "nm-disabled"), NM_UTILS_FLAGS2STR(NM_UNMANAGED_QUITTING, "quitting"), NM_UTILS_FLAGS2STR(NM_UNMANAGED_PLATFORM_INIT, "platform-init"), NM_UTILS_FLAGS2STR(NM_UNMANAGED_USER_EXPLICIT, "user-explicit"), @@ -15677,8 +15837,8 @@ unmanaged_flags_to_reason(NMUnmanagedFlags flags) /* Even if there are multiple flags, we can only return one reason. * Return the most important reason. */ - if (NM_FLAGS_HAS(flags, NM_UNMANAGED_SLEEPING)) - return NM_DEVICE_STATE_REASON_UNMANAGED_SLEEPING; + if (NM_FLAGS_HAS(flags, NM_UNMANAGED_MANAGER_DISABLED)) + return NM_DEVICE_STATE_REASON_UNMANAGED_MANAGER_DISABLED; if (NM_FLAGS_HAS(flags, NM_UNMANAGED_QUITTING)) return NM_DEVICE_STATE_REASON_UNMANAGED_QUITTING; if (NM_FLAGS_HAS(flags, NM_UNMANAGED_USER_SETTINGS)) @@ -16923,8 +17083,6 @@ _cleanup_generic_post(NMDevice *self, NMDeviceStateReason reason, CleanupType cl priv->v4_route_table_all_sync_before = FALSE; priv->v6_route_table_all_sync_before = FALSE; - priv->refresh_forwarding_done = FALSE; - priv->mtu_force_set_done = FALSE; priv->needs_ip6_subnet = FALSE; @@ -16970,7 +17128,6 @@ nm_device_cleanup(NMDevice *self, NMDeviceStateReason reason, CleanupType cleanu NMDevicePrivate *priv; NMDeviceClass *klass = NM_DEVICE_GET_CLASS(self); int ifindex; - gint32 default_forwarding_v4; g_return_if_fail(NM_IS_DEVICE(self)); @@ -16993,17 +17150,6 @@ nm_device_cleanup(NMDevice *self, NMDeviceStateReason reason, CleanupType cleanu nm_device_sysctl_ip_conf_set(self, AF_INET6, "use_tempaddr", "0"); } - /* Restoring the device's forwarding to the sysctl default is necessary because - * `refresh_forwarding()` only updates forwarding on activated devices. */ - default_forwarding_v4 = nm_platform_sysctl_get_int32( - nm_device_get_platform(self), - NMP_SYSCTL_PATHID_ABSOLUTE("/proc/sys/net/ipv4/conf/default/forwarding"), - 0); - nm_device_sysctl_ip_conf_set(self, - AF_INET, - "forwarding", - default_forwarding_v4 == 1 ? "1" : "0"); - /* Call device type-specific deactivation */ if (klass->deactivate) klass->deactivate(self); @@ -18947,19 +19093,6 @@ nm_device_get_hostname_from_dns_lookup(NMDevice *self, int addr_family, gboolean return nm_assert_unreachable_val(NULL); } -gboolean -nm_device_get_refresh_forwarding_done(NMDevice *self) -{ - return NM_DEVICE_GET_PRIVATE(self)->refresh_forwarding_done; -} - -void -nm_device_set_refresh_forwarding_done(NMDevice *self, gboolean is_refresh_forwarding_done) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - priv->refresh_forwarding_done = is_refresh_forwarding_done; -} - /*****************************************************************************/ static const char * diff --git a/src/core/devices/nm-device.h b/src/core/devices/nm-device.h index 9a663c2a..8632944a 100644 --- a/src/core/devices/nm-device.h +++ b/src/core/devices/nm-device.h @@ -581,7 +581,8 @@ void nm_device_copy_ip6_dns_config(NMDevice *self, NMDevice *from_device); /** * NMUnmanagedFlags: * @NM_UNMANAGED_NONE: placeholder value - * @NM_UNMANAGED_SLEEPING: %TRUE when unmanaged because NM is sleeping. + * @NM_UNMANAGED_MANAGER_DISABLED: %TRUE when unmanaged because NM is disabled. + * Currently, this happens when sleeping or with networking disabled. * @NM_UNMANAGED_QUITTING: %TRUE when unmanaged because NM is shutting down. * @NM_UNMANAGED_PLATFORM_INIT: %TRUE when unmanaged because platform link not * yet initialized. Unrealized device are also unmanaged for this reason. @@ -610,11 +611,11 @@ typedef enum { /* these flags are authoritative. If one of them is set, * the device cannot be managed. */ - NM_UNMANAGED_SLEEPING = (1LL << 0), - NM_UNMANAGED_QUITTING = (1LL << 1), - NM_UNMANAGED_PLATFORM_INIT = (1LL << 2), - NM_UNMANAGED_USER_EXPLICIT = (1LL << 3), - NM_UNMANAGED_USER_SETTINGS = (1LL << 4), + NM_UNMANAGED_MANAGER_DISABLED = (1LL << 0), + NM_UNMANAGED_QUITTING = (1LL << 1), + NM_UNMANAGED_PLATFORM_INIT = (1LL << 2), + NM_UNMANAGED_USER_EXPLICIT = (1LL << 3), + NM_UNMANAGED_USER_SETTINGS = (1LL << 4), /* These flags can be non-effective and be overwritten * by other flags. */ @@ -852,14 +853,4 @@ void nm_routing_rules_sync(NMConnection *applied_connection, NMDevice *self, NMNetns *netns); -NMSettingIPConfigForwarding nm_device_get_ipv4_forwarding(NMDevice *self); - -const char *nm_device_get_effective_ip_config_method(NMDevice *self, int addr_family); - -char *nm_device_sysctl_ip_conf_get(NMDevice *self, int addr_family, const char *property); - -gboolean nm_device_get_refresh_forwarding_done(NMDevice *self); - -void nm_device_set_refresh_forwarding_done(NMDevice *self, gboolean is_refresh_forwarding_done); - #endif /* __NETWORKMANAGER_DEVICE_H__ */ diff --git a/src/core/devices/ovs/nm-ovsdb.c b/src/core/devices/ovs/nm-ovsdb.c index 164bfd35..1c9484c4 100644 --- a/src/core/devices/ovs/nm-ovsdb.c +++ b/src/core/devices/ovs/nm-ovsdb.c @@ -1460,40 +1460,42 @@ _delete_interface(NMOvsdb *self, json_t *params, const char *ifname) json_array_append_new(new_interfaces, json_pack("[s,s]", "uuid", interface_uuid)); } - if (num_nm_interfaces == 0) { - /* The port no longer has any NM interface. Don't add it to "new_ports" and set - * ports_changed=TRUE, so that it will be deleted. */ + if (interfaces_changed && num_nm_interfaces == 0) { + /* We are deleting the last nm-interface of this port. Don't add it to "new_ports" + * and set ports_changed=TRUE, so that it will be deleted. */ ports_changed = TRUE; } else { + /* Keep this port: it's still alive, or it's unrelated to the deleted interface */ + json_array_append_new(new_ports, json_pack("[s,s]", "uuid", port_uuid)); + if (ovs_port->connection_uuid) + num_nm_ports++; + if (interfaces_changed) { - /* An interface needs to be deleted from this port */ + /* This port is still alive, but an interface needs to be deleted from it */ _expect_port_interfaces(params, ovs_port->name, interfaces); _set_port_interfaces(params, ovs_port->name, new_interfaces); } - /* The port is still alive */ - json_array_append_new(new_ports, json_pack("[s,s]", "uuid", port_uuid)); - if (ovs_port->connection_uuid) - num_nm_ports++; } } - if (num_nm_ports == 0) { - /* The bridge no longer has any NM port. Don't add it to "new_bridges" and set - * bridges_changed=TRUE, so that it will be deleted. */ + if (ports_changed && num_nm_ports == 0) { + /* We are deleting the last nm-port of this bridge. Don't add it to "new_bridges" + * and set bridges_changed=TRUE, so that it will be deleted. */ bridges_changed = TRUE; } else { + /* Keep this bridge: it's still alive, or it's unrelated to the deleted interface */ + json_array_append_new(new_bridges, json_pack("[s,s]", "uuid", ovs_bridge->bridge_uuid)); + if (ports_changed) { - /* A port needs to be deleted from this bridge */ + /* This bridge is still alive, but a port needs to be deleted from it */ _expect_bridge_ports(params, ovs_bridge->name, ports); _set_bridge_ports(params, ovs_bridge->name, new_ports); } - /* The bridge is still alive */ - json_array_append_new(new_bridges, json_pack("[s,s]", "uuid", ovs_bridge->bridge_uuid)); } } if (bridges_changed) { - /* A port needs to be deleted from this bridge */ + /* A bridge needs to be deleted */ _expect_ovs_bridges(params, priv->db_uuid, bridges); _set_ovs_bridges(params, priv->db_uuid, new_bridges); } diff --git a/src/core/nm-manager.c b/src/core/nm-manager.c index 9dc7bc01..87dde2c3 100644 --- a/src/core/nm-manager.c +++ b/src/core/nm-manager.c @@ -136,6 +136,7 @@ enum { ACTIVE_CONNECTION_REMOVED, CONFIGURE_QUIT, DEVICE_IFINDEX_CHANGED, + SHARING_IPV4_CHANGED, LAST_SIGNAL }; @@ -238,6 +239,8 @@ typedef struct { guint8 device_state_prune_ratelimit_count; + guint shared_connections_ip4_count; + bool startup : 1; bool devices_inited : 1; @@ -1960,7 +1963,7 @@ find_device_by_iface(NMManager *self, } static gboolean -manager_sleeping(NMManager *self) +manager_is_disabled(NMManager *self) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); @@ -1973,8 +1976,8 @@ static const char * _nm_state_to_string(NMState state) { switch (state) { - case NM_STATE_ASLEEP: - return "ASLEEP"; + case NM_STATE_DISABLED: + return "DISABLED"; case NM_STATE_DISCONNECTED: return "DISCONNECTED"; case NM_STATE_DISCONNECTING: @@ -2078,15 +2081,18 @@ nm_manager_update_state(NMManager *self) { NMManagerPrivate *priv; NMState new_state = NM_STATE_DISCONNECTED; + const char *detail = ""; g_return_if_fail(NM_IS_MANAGER(self)); priv = NM_MANAGER_GET_PRIVATE(self); - if (manager_sleeping(self)) - new_state = NM_STATE_ASLEEP; - else + if (manager_is_disabled(self)) { + new_state = NM_STATE_DISABLED; + detail = priv->sleeping ? " (ASLEEP)" : " (NETWORKING OFF)"; + } else { new_state = find_best_device_state(self); + } if (new_state >= NM_STATE_CONNECTED_LOCAL && priv->connectivity_state == NM_CONNECTIVITY_FULL) { new_state = NM_STATE_CONNECTED_GLOBAL; @@ -2097,7 +2103,7 @@ nm_manager_update_state(NMManager *self) priv->state = new_state; - _LOGI(LOGD_CORE, "NetworkManager state is now %s", _nm_state_to_string(new_state)); + _LOGI(LOGD_CORE, "NetworkManager state is now %s%s", _nm_state_to_string(new_state), detail); _notify(self, PROP_STATE); nm_dbus_object_emit_signal(NM_DBUS_OBJECT(self), @@ -2956,7 +2962,7 @@ _rfkill_update_devices(NMManager *self, NMRfkillType rtype, gboolean enabled) _notify(self, _rfkill_type_desc[rtype].prop_id); /* Don't touch devices if asleep/networking disabled */ - if (manager_sleeping(self)) + if (manager_is_disabled(self)) return; /* enable/disable wireless devices as required */ @@ -3120,7 +3126,7 @@ _rfkill_update_from_user(NMManager *self, NMRfkillType rtype, gboolean enabled) gboolean old_enabled, new_enabled; /* Don't touch devices if asleep/networking disabled */ - if (manager_sleeping(self)) + if (manager_is_disabled(self)) return; _LOGD(LOGD_RFKILL, @@ -4079,7 +4085,7 @@ add_device(NMManager *self, NMDevice *device, GError **error) nm_device_set_unmanaged_by_user_settings(device, TRUE); - nm_device_set_unmanaged_flags(device, NM_UNMANAGED_SLEEPING, manager_sleeping(self)); + nm_device_set_unmanaged_flags(device, NM_UNMANAGED_MANAGER_DISABLED, manager_is_disabled(self)); dbus_path = nm_dbus_object_export(NM_DBUS_OBJECT(device)); _LOG2I(LOGD_DEVICE, device, "new %s device (%s)", type_desc, dbus_path); @@ -7299,7 +7305,7 @@ device_sleep_cb(NMDevice *device, GParamSpec *pspec, NMManager *self) case NM_DEVICE_STATE_DISCONNECTED: _LOGD(LOGD_SUSPEND, "sleep: unmanaging device %s", nm_device_get_ip_iface(device)); nm_device_set_unmanaged_by_flags_queue(device, - NM_UNMANAGED_SLEEPING, + NM_UNMANAGED_MANAGER_DISABLED, NM_UNMAN_FLAG_OP_SET_UNMANAGED, NM_DEVICE_STATE_REASON_SLEEPING); break; @@ -7321,24 +7327,26 @@ _handle_device_takedown(NMManager *self, gboolean suspending, gboolean is_shutdown) { + gboolean is_sleep = suspending || is_shutdown; + NMDeviceStateReason reason = + is_sleep ? NM_DEVICE_STATE_REASON_SLEEPING : NM_DEVICE_STATE_REASON_NETWORKING_OFF; + nm_device_notify_sleeping(device); if (nm_device_is_activating(device) || nm_device_get_state(device) == NM_DEVICE_STATE_ACTIVATED) { - _LOGD(LOGD_SUSPEND, + _LOGD(is_sleep ? LOGD_SUSPEND : LOGD_CORE, "%s: wait disconnection of device %s", - is_shutdown ? "shutdown" : "sleep", + is_sleep ? (is_shutdown ? "shutdown" : "sleep") : "networking off", nm_device_get_ip_iface(device)); if (sleep_devices_add(self, device, suspending)) - nm_device_queue_state(device, - NM_DEVICE_STATE_DEACTIVATING, - NM_DEVICE_STATE_REASON_SLEEPING); + nm_device_queue_state(device, NM_DEVICE_STATE_DEACTIVATING, reason); } else { nm_device_set_unmanaged_by_flags(device, - NM_UNMANAGED_SLEEPING, + NM_UNMANAGED_MANAGER_DISABLED, NM_UNMAN_FLAG_OP_SET_UNMANAGED, - NM_DEVICE_STATE_REASON_SLEEPING); + reason); } } @@ -7352,8 +7360,10 @@ do_sleep_wake(NMManager *self, gboolean sleeping_changed) suspending = sleeping_changed && priv->sleeping; waking_from_suspend = sleeping_changed && !priv->sleeping; - if (manager_sleeping(self)) { - _LOGD(LOGD_SUSPEND, "sleep: %s...", suspending ? "sleeping" : "disabling"); + if (manager_is_disabled(self)) { + _LOGD(suspending ? LOGD_SUSPEND : LOGD_CORE, + "%s...", + suspending ? "sleep: sleeping" : "networking: disabling"); /* FIXME: are there still hardware devices that need to be disabled around * suspend/resume? @@ -7379,7 +7389,9 @@ do_sleep_wake(NMManager *self, gboolean sleeping_changed) _handle_device_takedown(self, device, suspending, FALSE); } } else { - _LOGD(LOGD_SUSPEND, "sleep: %s...", waking_from_suspend ? "waking up" : "re-enabling"); + _LOGD(waking_from_suspend ? LOGD_SUSPEND : LOGD_CORE, + "%s...", + waking_from_suspend ? "sleep: waking up" : "networking: re-enabling"); sleep_devices_clear(self); @@ -7393,7 +7405,7 @@ do_sleep_wake(NMManager *self, gboolean sleeping_changed) */ if (device_is_wake_on_lan(priv->platform, device)) nm_device_set_unmanaged_by_flags(device, - NM_UNMANAGED_SLEEPING, + NM_UNMANAGED_MANAGER_DISABLED, NM_UNMAN_FLAG_OP_SET_UNMANAGED, NM_DEVICE_STATE_REASON_SLEEPING); @@ -7421,10 +7433,12 @@ do_sleep_wake(NMManager *self, gboolean sleeping_changed) guint i; if (nm_device_is_software(device) - && !nm_device_get_unmanaged_flags(device, NM_UNMANAGED_SLEEPING)) { + && !nm_device_get_unmanaged_flags(device, NM_UNMANAGED_MANAGER_DISABLED)) { /* DHCP leases of software devices could have gone stale * so we need to renew them. */ - nm_device_update_dynamic_ip_setup(device, "wake up"); + nm_device_update_dynamic_ip_setup(device, + waking_from_suspend ? "wake up" + : "networking on"); continue; } @@ -7455,7 +7469,7 @@ do_sleep_wake(NMManager *self, gboolean sleeping_changed) ? NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED : NM_DEVICE_STATE_REASON_NOW_MANAGED; nm_device_set_unmanaged_by_flags(device, - NM_UNMANAGED_SLEEPING, + NM_UNMANAGED_MANAGER_DISABLED, NM_UNMAN_FLAG_OP_SET_MANAGED, reason); } @@ -8818,6 +8832,41 @@ nm_manager_emit_device_ifindex_changed(NMManager *self, NMDevice *device) g_signal_emit(self, signals[DEVICE_IFINDEX_CHANGED], 0, device); } +void +nm_manager_update_shared_connection(NMManager *self, int addr_family, gboolean enabled) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + gboolean state_changed, state; + + /* Only IPv4 supported for the moment */ + if (addr_family != AF_INET) + return; + + if (enabled) { + g_return_if_fail(priv->shared_connections_ip4_count < G_MAXUINT); + priv->shared_connections_ip4_count++; + state_changed = priv->shared_connections_ip4_count == 1; + } else { + g_return_if_fail(priv->shared_connections_ip4_count > 0); + priv->shared_connections_ip4_count--; + state_changed = priv->shared_connections_ip4_count == 0; + } + + if (state_changed) { + state = priv->shared_connections_ip4_count > 0; + _LOGD(LOGD_SHARING, "sharing-ipv4 state change %d -> %d", !state, state); + g_signal_emit(self, signals[SHARING_IPV4_CHANGED], 0, state); + } +} + +gboolean +nm_manager_get_sharing_ipv4(NMManager *self) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + + return priv->shared_connections_ip4_count > 0; +} + /*****************************************************************************/ NM_DEFINE_SINGLETON_REGISTER(NMManager); @@ -9921,6 +9970,17 @@ nm_manager_class_init(NMManagerClass *manager_class) G_TYPE_NONE, 1, NM_TYPE_DEVICE); + + signals[SHARING_IPV4_CHANGED] = g_signal_new(NM_MANAGER_SHARING_IPV4_CHANGED, + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_FIRST, + 0, + NULL, + NULL, + NULL, + G_TYPE_NONE, + 1, + G_TYPE_BOOLEAN); } NMConfig * diff --git a/src/core/nm-manager.h b/src/core/nm-manager.h index 3c5213c4..e10ca0d1 100644 --- a/src/core/nm-manager.h +++ b/src/core/nm-manager.h @@ -61,6 +61,7 @@ #define NM_MANAGER_CONFIGURE_QUIT "configure-quit" #define NM_MANAGER_INTERNAL_DEVICE_ADDED "internal-device-added" #define NM_MANAGER_INTERNAL_DEVICE_REMOVED "internal-device-removed" +#define NM_MANAGER_SHARING_IPV4_CHANGED "sharing-ipv4-changed" GType nm_manager_get_type(void); @@ -212,6 +213,9 @@ struct _NMDnsManager; struct _NMDnsManager *nm_manager_get_dns_manager(NMManager *self); +void nm_manager_update_shared_connection(NMManager *self, int addr_family, gboolean enabled); +gboolean nm_manager_get_sharing_ipv4(NMManager *self); + /*****************************************************************************/ void nm_manager_notify_delete_settings_connections(NMManager *self, diff --git a/src/core/nm-policy.c b/src/core/nm-policy.c index fbcee40d..0288795e 100644 --- a/src/core/nm-policy.c +++ b/src/core/nm-policy.c @@ -18,7 +18,6 @@ #include "NetworkManagerUtils.h" #include "devices/nm-device.h" #include "devices/nm-device-factory.h" -#include "devices/nm-device-private.h" #include "dns/nm-dns-manager.h" #include "nm-act-request.h" #include "nm-auth-utils.h" @@ -98,6 +97,7 @@ typedef struct { bool updating_dns : 1; GArray *ip6_prefix_delegations; /* pool of ip6 prefixes delegated to all devices */ + } NMPolicyPrivate; struct _NMPolicy { @@ -1845,7 +1845,7 @@ nm_policy_device_recheck_auto_activate_schedule(NMPolicy *self, NMDevice *device priv = NM_POLICY_GET_PRIVATE(self); - if (nm_manager_get_state(priv->manager) == NM_STATE_ASLEEP) + if (nm_manager_get_state(priv->manager) == NM_STATE_DISABLED) return; if (!nm_device_autoconnect_allowed(device)) @@ -2084,65 +2084,6 @@ unblock_autoconnect_for_ports_for_sett_conn(NMPolicy *self, NMSettingsConnection } static void -refresh_forwarding(NMPolicy *self, NMDevice *device, gboolean is_activated_shared_device) -{ - NMActiveConnection *ac; - NMDevice *tmp_device; - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self); - const CList *tmp_lst; - gboolean any_shared_active = false; - gint32 default_forwarding_v4; - const char *new_value = NULL; - - /* FIXME: This implementation is still inefficient because refresh_forwarding() - * is called every time a device goes up or down, requiring a full scan of all - * active connections to determine if any shared connection is active. */ - nm_manager_for_each_active_connection (priv->manager, ac, tmp_lst) { - NMSettingIPConfig *s_ip; - NMDevice *to_device = nm_active_connection_get_device(ac); - - if (to_device) { - s_ip = nm_device_get_applied_setting(to_device, NM_TYPE_SETTING_IP4_CONFIG); - if (s_ip) { - if (nm_streq0(nm_device_get_effective_ip_config_method(to_device, AF_INET), - NM_SETTING_IP4_CONFIG_METHOD_SHARED)) { - any_shared_active = true; - break; - } - } - } - } - - default_forwarding_v4 = nm_platform_sysctl_get_int32( - NM_PLATFORM_GET, - NMP_SYSCTL_PATHID_ABSOLUTE("/proc/sys/net/ipv4/conf/default/forwarding"), - 0); - - new_value = any_shared_active ? "1" : (default_forwarding_v4 ? "1" : "0"); - - nm_manager_for_each_device (priv->manager, tmp_device, tmp_lst) { - NMDeviceState state; - NMSettingIPConfigForwarding ipv4_forwarding; - - state = nm_device_get_state(tmp_device); - if (state != NM_DEVICE_STATE_ACTIVATED) - continue; - - ipv4_forwarding = nm_device_get_ipv4_forwarding(tmp_device); - - if (ipv4_forwarding == NM_SETTING_IP_CONFIG_FORWARDING_AUTO - || (device == tmp_device && is_activated_shared_device)) { - gs_free char *sysctl_value = NULL; - - sysctl_value = nm_device_sysctl_ip_conf_get(tmp_device, AF_INET, "forwarding"); - - if (!nm_streq0(sysctl_value, new_value)) - nm_device_sysctl_ip_conf_set(tmp_device, AF_INET, "forwarding", new_value); - } - } -} - -static void activate_port_or_children_connections(NMPolicy *self, NMDevice *device, gboolean activate_children_connections_only) @@ -2286,9 +2227,8 @@ device_state_changed(NMDevice *device, NMPolicyPrivate *priv = user_data; NMPolicy *self = _PRIV_TO_SELF(priv); NMActiveConnection *ac; - NMSettingsConnection *sett_conn = nm_device_get_settings_connection(device); - NMSettingConnection *s_con = NULL; - gboolean is_activated_shared_device = FALSE; + NMSettingsConnection *sett_conn = nm_device_get_settings_connection(device); + NMSettingConnection *s_con = NULL; switch (nm_device_state_reason_check(reason)) { case NM_DEVICE_STATE_REASON_GSM_SIM_PIN_REQUIRED: @@ -2404,10 +2344,6 @@ device_state_changed(NMDevice *device, } } } - if (!nm_device_get_refresh_forwarding_done(device)) { - refresh_forwarding(self, device, FALSE); - nm_device_set_refresh_forwarding_done(device, TRUE); - } break; case NM_DEVICE_STATE_ACTIVATED: if (nm_device_get_device_type(device) == NM_DEVICE_TYPE_OVS_INTERFACE) { @@ -2440,20 +2376,11 @@ device_state_changed(NMDevice *device, update_system_hostname(self, "routing and dns", TRUE); nm_dns_manager_end_updates(priv->dns_manager, __func__); - is_activated_shared_device = - nm_streq0(nm_device_get_effective_ip_config_method(device, AF_INET), - NM_SETTING_IP4_CONFIG_METHOD_SHARED); - refresh_forwarding(self, device, is_activated_shared_device); - nm_device_set_refresh_forwarding_done(device, FALSE); break; case NM_DEVICE_STATE_UNMANAGED: case NM_DEVICE_STATE_UNAVAILABLE: if (old_state > NM_DEVICE_STATE_DISCONNECTED) update_routing_and_dns(self, FALSE, device); - if (!nm_device_get_refresh_forwarding_done(device)) { - refresh_forwarding(self, device, FALSE); - nm_device_set_refresh_forwarding_done(device, TRUE); - } break; case NM_DEVICE_STATE_DEACTIVATING: if (sett_conn) { @@ -2489,10 +2416,6 @@ device_state_changed(NMDevice *device, } } ip6_remove_device_prefix_delegations(self, device); - if (!nm_device_get_refresh_forwarding_done(device)) { - refresh_forwarding(self, device, FALSE); - nm_device_set_refresh_forwarding_done(device, TRUE); - } break; case NM_DEVICE_STATE_DISCONNECTED: g_signal_handlers_disconnect_by_func(device, device_dns_lookup_done, self); @@ -2509,10 +2432,6 @@ device_state_changed(NMDevice *device, /* Device is now available for auto-activation */ nm_policy_device_recheck_auto_activate_schedule(self, device); - if (!nm_device_get_refresh_forwarding_done(device)) { - refresh_forwarding(self, device, FALSE); - nm_device_set_refresh_forwarding_done(device, TRUE); - } break; case NM_DEVICE_STATE_PREPARE: @@ -2528,10 +2447,6 @@ device_state_changed(NMDevice *device, g_object_weak_unref(G_OBJECT(ac), pending_ac_gone, self); g_object_unref(self); } - if (!nm_device_get_refresh_forwarding_done(device)) { - refresh_forwarding(self, device, FALSE); - nm_device_set_refresh_forwarding_done(device, TRUE); - } break; case NM_DEVICE_STATE_IP_CONFIG: /* We must have secrets if we got here. */ @@ -2542,10 +2457,6 @@ device_state_changed(NMDevice *device, sett_conn, NM_SETTINGS_AUTOCONNECT_BLOCKED_REASON_FAILED, FALSE); - if (!nm_device_get_refresh_forwarding_done(device)) { - refresh_forwarding(self, device, FALSE); - nm_device_set_refresh_forwarding_done(device, TRUE); - } break; case NM_DEVICE_STATE_SECONDARIES: if (sett_conn) |