diff options
| author | Michael Biebl <biebl@debian.org> | 2025-08-01 19:15:13 +0200 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2025-08-01 19:15:13 +0200 |
| commit | 7e9091a5960f67a84787c03153324915220e4816 (patch) | |
| tree | dc743de962532932ebc3b4ed3a36ddd093d97d68 /src/core/devices | |
| parent | 582eb4472a0f3375042afb9026cbeb50e058a27d (diff) | |
New upstream version 1.54.0 upstream/1.54.0
Diffstat (limited to 'src/core/devices')
| -rw-r--r-- | src/core/devices/nm-device-bond.c | 16 | ||||
| -rw-r--r-- | src/core/devices/nm-device-bridge.c | 5 | ||||
| -rw-r--r-- | src/core/devices/nm-device-hsr.c | 4 | ||||
| -rw-r--r-- | src/core/devices/nm-device-tun.c | 8 | ||||
| -rw-r--r-- | src/core/devices/nm-device-vrf.c | 2 | ||||
| -rw-r--r-- | src/core/devices/nm-device.c | 177 | ||||
| -rw-r--r-- | src/core/devices/nm-device.h | 12 | ||||
| -rw-r--r-- | src/core/devices/nm-lldp-listener.c | 2 | ||||
| -rw-r--r-- | src/core/devices/ovs/nm-device-ovs-bridge.c | 28 | ||||
| -rw-r--r-- | src/core/devices/ovs/nm-device-ovs-interface.c | 58 | ||||
| -rw-r--r-- | src/core/devices/ovs/nm-device-ovs-port.c | 28 | ||||
| -rw-r--r-- | src/core/devices/ovs/nm-ovs-factory.c | 27 | ||||
| -rw-r--r-- | src/core/devices/ovs/nm-ovsdb.c | 80 |
13 files changed, 319 insertions, 128 deletions
diff --git a/src/core/devices/nm-device-bond.c b/src/core/devices/nm-device-bond.c index 53b32466..673d2361 100644 --- a/src/core/devices/nm-device-bond.c +++ b/src/core/devices/nm-device-bond.c @@ -137,13 +137,13 @@ _set_bond_attr(NMDevice *device, const char *attr, const char *value) return ret; } -#define _set_bond_attr_take(device, attr, value) \ - G_STMT_START \ - { \ - gs_free char *_tmp = (value); \ - \ - _set_bond_attr(device, NM_SETTING_BOND_OPTION_ARP_IP_TARGET, _tmp); \ - } \ +#define _set_bond_attr_take(device, attr, value) \ + G_STMT_START \ + { \ + gs_free char *_tmp = (value); \ + \ + _set_bond_attr(device, attr, _tmp); \ + } \ G_STMT_END #define _set_bond_attr_printf(device, attr, fmt, ...) \ @@ -902,7 +902,7 @@ reapply_connection(NMDevice *device, NMConnection *con_old, NMConnection *con_ne mode = _nm_setting_bond_mode_from_string(value); g_return_if_fail(mode != NM_BOND_MODE_UNKNOWN); - /* Below we set only the bond options that kernel allows to modify + /* Below we set only the bond options that the kernel allows modifying * while keeping the bond interface up */ set_bond_arp_ip_targets(device, s_bond); diff --git a/src/core/devices/nm-device-bridge.c b/src/core/devices/nm-device-bridge.c index 7c34fde0..45cdd83f 100644 --- a/src/core/devices/nm-device-bridge.c +++ b/src/core/devices/nm-device-bridge.c @@ -735,6 +735,11 @@ merge_bridge_vlan_default_pvid(NMPlatformBridgeVlan *vlans, guint *num_vlans, gu gboolean has_pvid = FALSE; guint i; + if (default_pvid == 0) { + /* default_pvid=0 means that the default PVID is disabled. No need to merge it. */ + return vlans; + } + for (i = 0; i < *num_vlans; i++) { if (vlans[i].pvid) { has_pvid = TRUE; diff --git a/src/core/devices/nm-device-hsr.c b/src/core/devices/nm-device-hsr.c index 8156fa77..59454ee3 100644 --- a/src/core/devices/nm-device-hsr.c +++ b/src/core/devices/nm-device-hsr.c @@ -94,8 +94,10 @@ update_properties(NMDevice *device) CHECK_PROPERTY_CHANGED(multicast_spec, PROP_MULTICAST_SPEC); CHECK_PROPERTY_CHANGED(prp, PROP_PRP); - if (!nm_ether_addr_equal(&priv->props.supervision_address, &props->supervision_address)) + if (!nm_ether_addr_equal(&priv->props.supervision_address, &props->supervision_address)) { + priv->props.supervision_address = props->supervision_address; _notify(self, PROP_SUPERVISION_ADDRESS); + } g_object_thaw_notify((GObject *) device); } diff --git a/src/core/devices/nm-device-tun.c b/src/core/devices/nm-device-tun.c index faab86d0..b277c378 100644 --- a/src/core/devices/nm-device-tun.c +++ b/src/core/devices/nm-device-tun.c @@ -242,12 +242,14 @@ create_and_realize(NMDevice *device, g_return_val_if_reached(FALSE); } - owner = _nm_utils_ascii_str_to_int64(nm_setting_tun_get_owner(s_tun), 10, 0, G_MAXINT32, -1); + owner = + _nm_utils_ascii_str_to_int64(nm_setting_tun_get_owner(s_tun), 10, 0, G_MAXUINT32 - 1, -1); if (owner != -1) { props.owner_valid = TRUE; props.owner = owner; } - group = _nm_utils_ascii_str_to_int64(nm_setting_tun_get_group(s_tun), 10, 0, G_MAXINT32, -1); + group = + _nm_utils_ascii_str_to_int64(nm_setting_tun_get_group(s_tun), 10, 0, G_MAXUINT32 - 1, -1); if (group != -1) { props.group_valid = TRUE; props.group = group; @@ -278,7 +280,7 @@ _same_og(const char *str, gboolean og_valid, guint32 og_num) { gint64 v; - v = _nm_utils_ascii_str_to_int64(str, 10, 0, G_MAXINT32, -1); + v = _nm_utils_ascii_str_to_int64(str, 10, 0, G_MAXUINT32 - 1, -1); return (!og_valid && (v == (gint64) -1)) || (og_valid && (((guint32) v) == og_num)); } diff --git a/src/core/devices/nm-device-vrf.c b/src/core/devices/nm-device-vrf.c index 7dfd6504..6d272a95 100644 --- a/src/core/devices/nm-device-vrf.c +++ b/src/core/devices/nm-device-vrf.c @@ -235,7 +235,7 @@ attach_port(NMDevice *device, _LOGI(LOGD_DEVICE, "attached VRF port %s", port_iface); } else - _LOGI(LOGD_BOND, "VRF port %s was attached", port_iface); + _LOGI(LOGD_DEVICE, "VRF port %s was attached", port_iface); return TRUE; } diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c index 2f2f25a5..f6057e52 100644 --- a/src/core/devices/nm-device.c +++ b/src/core/devices/nm-device.c @@ -779,6 +779,7 @@ 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) @@ -880,6 +881,7 @@ static void device_ifindex_changed_cb(NMManager *manager, NMDevice *device_chang static gboolean device_link_changed(gpointer user_data); static gboolean _get_maybe_ipv6_disabled(NMDevice *self); static void deactivate_ready(NMDevice *self, NMDeviceStateReason reason); +static void carrier_disconnected_action_cancel(NMDevice *self); /*****************************************************************************/ @@ -1414,6 +1416,26 @@ _prop_get_connection_mdns(NMDevice *self) NM_SETTING_CONNECTION_MDNS_DEFAULT); } +static gboolean +_prop_get_sriov_preserve_on_down(NMDevice *self, NMSettingSriov *s_sriov) +{ + NMSriovPreserveOnDown preserve; + + g_return_val_if_fail(NM_IS_DEVICE(self), FALSE); + g_return_val_if_fail(NM_IS_SETTING_SRIOV(s_sriov), FALSE); + + preserve = nm_setting_sriov_get_preserve_on_down(s_sriov); + if (NM_IN_SET(preserve, NM_SRIOV_PRESERVE_ON_DOWN_NO, NM_SRIOV_PRESERVE_ON_DOWN_YES)) + return preserve; + + return nm_config_data_get_connection_default_int64(NM_CONFIG_GET_DATA, + NM_CON_DEFAULT("sriov.preserve-on-down"), + self, + NM_SRIOV_PRESERVE_ON_DOWN_NO, + NM_SRIOV_PRESERVE_ON_DOWN_YES, + NM_SRIOV_PRESERVE_ON_DOWN_NO); +} + static NMSettingConnectionLlmnr _prop_get_connection_llmnr(NMDevice *self) { @@ -2109,6 +2131,33 @@ _prop_get_ipvx_dhcp_send_hostname(NMDevice *self, int addr_family) return send_hostname_v2; } +NMSettingIPConfigForwarding +nm_device_get_ipv4_forwarding(NMDevice *self) +{ + NMSettingIPConfig *s_ip; + NMSettingIPConfigForwarding forwarding; + + g_return_val_if_fail(NM_IS_DEVICE(self), NM_SETTING_IP_CONFIG_FORWARDING_AUTO); + + s_ip = nm_device_get_applied_setting(self, NM_TYPE_SETTING_IP4_CONFIG); + if (s_ip) + forwarding = nm_setting_ip_config_get_forwarding(s_ip); + else + forwarding = NM_SETTING_IP_CONFIG_FORWARDING_DEFAULT; + + if (forwarding == NM_SETTING_IP_CONFIG_FORWARDING_DEFAULT) { + forwarding = + nm_config_data_get_connection_default_int64(NM_CONFIG_GET_DATA, + NM_CON_DEFAULT("ipv4.forwarding"), + self, + NM_SETTING_IP_CONFIG_FORWARDING_NO, + NM_SETTING_IP_CONFIG_FORWARDING_AUTO, + NM_SETTING_IP_CONFIG_FORWARDING_AUTO); + } + + return forwarding; +} + static gboolean _prop_get_connection_ip_ping_addresses_require_all(NMDevice *self, NMSettingConnection *s_con) { @@ -2717,7 +2766,7 @@ _ethtool_features_set(NMDevice *self, if (nm_setting_ethtool_init_features(s_ethtool, ethtool_state->requested) == 0) return; - features = nm_platform_ethtool_get_link_features(platform, ethtool_state->ifindex); + features = nm_platform_ethtool_get_features(platform, ethtool_state->ifindex); if (!features) { _LOGW(LOGD_DEVICE, "ethtool: failure setting offload features (cannot read features)"); return; @@ -2836,9 +2885,9 @@ _ethtool_coalesce_set(NMDevice *self, continue; if (!has_old) { - if (!nm_platform_ethtool_get_link_coalesce(platform, - ethtool_state->ifindex, - &coalesce_old)) { + if (!nm_platform_ethtool_get_coalesce(platform, + ethtool_state->ifindex, + &coalesce_old)) { _LOGW(LOGD_DEVICE, "ethtool: failure getting coalesce settings (cannot read)"); return; } @@ -2917,7 +2966,7 @@ _ethtool_ring_set(NMDevice *self, nm_assert(g_variant_is_of_type(variant, G_VARIANT_TYPE_UINT32)); if (!has_old) { - if (!nm_platform_ethtool_get_link_ring(platform, ethtool_state->ifindex, &ring_old)) { + if (!nm_platform_ethtool_get_ring(platform, ethtool_state->ifindex, &ring_old)) { _LOGW(LOGD_DEVICE, "ethtool: failure setting ring options (cannot read existing setting)"); return; @@ -3013,9 +3062,9 @@ _ethtool_channels_set(NMDevice *self, nm_assert(g_variant_is_of_type(variant, G_VARIANT_TYPE_UINT32)); if (!has_old) { - if (!nm_platform_ethtool_get_link_channels(platform, - ethtool_state->ifindex, - &channels_old)) { + if (!nm_platform_ethtool_get_channels(platform, + ethtool_state->ifindex, + &channels_old)) { _LOGW(LOGD_DEVICE, "ethtool: failure setting channels options (cannot read existing setting)"); return; @@ -3132,7 +3181,7 @@ _ethtool_pause_set(NMDevice *self, nm_assert(g_variant_is_of_type(variant, G_VARIANT_TYPE_BOOLEAN)); if (!has_old) { - if (!nm_platform_ethtool_get_link_pause(platform, ethtool_state->ifindex, &pause_old)) { + if (!nm_platform_ethtool_get_pause(platform, ethtool_state->ifindex, &pause_old)) { _LOGW(LOGD_DEVICE, "ethtool: failure setting pause options (cannot read " "existing setting)"); @@ -3218,7 +3267,7 @@ _ethtool_eee_set(NMDevice *self, nm_assert(g_variant_is_of_type(variant, G_VARIANT_TYPE_BOOLEAN)); if (!has_old) { - if (!nm_platform_ethtool_get_link_eee(platform, ethtool_state->ifindex, &eee_old)) { + if (!nm_platform_ethtool_get_eee(platform, ethtool_state->ifindex, &eee_old)) { _LOGW(LOGD_DEVICE, "ethtool: failure setting eee options (cannot read " "existing setting)"); @@ -3729,7 +3778,7 @@ nm_device_assume_state_reset(NMDevice *self) /*****************************************************************************/ -static char * +char * nm_device_sysctl_ip_conf_get(NMDevice *self, int addr_family, const char *property) { const char *ifname; @@ -4993,6 +5042,10 @@ _set_ifindex(NMDevice *self, int ifindex, gboolean is_ip_ifindex) ip_ifindex_new = nm_device_get_ip_ifindex(self); + /* the ifindex changed; forget about any carrier change event for + * the previous ifindex */ + carrier_disconnected_action_cancel(self); + if (priv->l3cfg) { if (ip_ifindex_new <= 0 || ip_ifindex_new != nm_l3cfg_get_ifindex(priv->l3cfg)) { const NML3ConfigData *l3cd_old; @@ -6584,11 +6637,15 @@ concheck_update_state(NMDevice *self, _notify(self, IS_IPv4 ? PROP_IP4_CONNECTIVITY : PROP_IP6_CONNECTIVITY); - if (priv->state == NM_DEVICE_STATE_ACTIVATED && !nm_device_managed_type_is_external(self)) + /* State change could've affected the route metrics (removed the penalty + * once FULL connectivity is reached), redo the L3 configuration. */ + if (priv->state > NM_DEVICE_STATE_IP_CONFIG && priv->state < NM_DEVICE_STATE_DEACTIVATING + && !nm_device_managed_type_is_external(self)) { _dev_l3_register_l3cds(self, priv->l3cfg, TRUE, NM_TERNARY_DEFAULT); + } } -static const char * +const char * nm_device_get_effective_ip_config_method(NMDevice *self, int addr_family) { NMDeviceClass *klass; @@ -7725,9 +7782,7 @@ device_link_changed(gpointer user_data) * tagged for carrier ignore) ensure that when the carrier appears we * renew DHCP leases and such. */ - if (priv->state == NM_DEVICE_STATE_ACTIVATED) { - nm_device_update_dynamic_ip_setup(self, "interface got carrier"); - } + nm_device_update_dynamic_ip_setup(self, "interface got carrier"); } if (update_unmanaged_specs) @@ -8974,7 +9029,7 @@ nm_device_port_notify_attach_as_port(NMDevice *self, gboolean success) priv->is_attached = TRUE; - _notify(priv->controller, PROP_CONTROLLER); + _notify(self, PROP_CONTROLLER); nm_clear_pointer(&NM_DEVICE_GET_PRIVATE(priv->controller)->ports_variant, g_variant_unref); @@ -9053,7 +9108,7 @@ nm_device_port_notify_release(NMDevice *self, priv->is_attached = FALSE; - _notify(priv->controller, PROP_CONTROLLER); + _notify(self, PROP_CONTROLLER); nm_clear_pointer(&NM_DEVICE_GET_PRIVATE(priv->controller)->ports_variant, g_variant_unref); nm_gobject_notify_together(priv->controller, PROP_PORTS, PROP_SLAVES); @@ -9521,7 +9576,7 @@ nm_device_generate_connection(NMDevice *self, NM_SETTING_CONNECTION_ID, ifname, NM_SETTING_CONNECTION_AUTOCONNECT, - FALSE, + TRUE, NM_SETTING_CONNECTION_INTERFACE_NAME, ifname, NM_SETTING_CONNECTION_TIMESTAMP, @@ -11335,6 +11390,13 @@ _dev_ipdhcpx_notify(NMDhcpClient *client, const NMDhcpClientNotifyData *notify_d switch (notify_data->notify_type) { case NM_DHCP_CLIENT_NOTIFY_TYPE_PREFIX_DELEGATED: nm_assert(!IS_IPv4); + if (notify_data->prefix_delegated.prefix->plen == 0 + || notify_data->prefix_delegated.prefix->plen > 64) { + _LOGW_ipdhcp(addr_family, + "ignoring invalid prefix-delegation with length %u", + notify_data->prefix_delegated.prefix->plen); + return; + } /* Just re-emit. The device just contributes the prefix to the * pool in NMPolicy, which decides about subnet allocation * on the shared devices. */ @@ -13073,6 +13135,13 @@ 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); @@ -13369,7 +13438,8 @@ activate_stage3_ip_config(NMDevice *self) * IPv6LL if this is not an assumed connection, since assumed connections * will already have IPv6 set up. */ - if (!nm_device_managed_type_is_external_or_assume(self)) + if ((priv->state <= NM_DEVICE_STATE_IP_CONFIG || priv->ip_data_6.do_reapply) + && !nm_device_managed_type_is_external_or_assume(self)) _dev_addrgenmode6_set(self, NM_IN6_ADDR_GEN_MODE_NONE); /* Re-enable IPv6 on the interface */ @@ -13505,19 +13575,6 @@ _dev_ipshared4_init(NMDevice *self) } if (nm_platform_sysctl_get_int32(nm_device_get_platform(self), - NMP_SYSCTL_PATHID_ABSOLUTE("/proc/sys/net/ipv4/ip_forward"), - -1) - == 1) { - /* nothing to do. */ - } else if (!nm_platform_sysctl_set(nm_device_get_platform(self), - NMP_SYSCTL_PATHID_ABSOLUTE("/proc/sys/net/ipv4/ip_forward"), - "1")) { - errsv = errno; - _LOGW_ipshared(AF_INET, "error enabling IPv4 forwarding: %s", nm_strerror_native(errsv)); - return FALSE; - } - - if (nm_platform_sysctl_get_int32(nm_device_get_platform(self), NMP_SYSCTL_PATHID_ABSOLUTE("/proc/sys/net/ipv4/ip_dynaddr"), -1) == 1) { @@ -13994,13 +14051,18 @@ can_reapply_change(NMDevice *self, goto out_fail; } - if (NM_IN_STRSET(setting_name, - NM_SETTING_OVS_EXTERNAL_IDS_SETTING_NAME, - NM_SETTING_OVS_OTHER_CONFIG_SETTING_NAME) - && NM_DEVICE_GET_CLASS(self)->can_reapply_change_ovs_external_ids) { - /* TODO: this means, you cannot reapply changes to the external-ids for - * OVS system interfaces. */ - return TRUE; + if (nm_streq(setting_name, NM_SETTING_BRIDGE_PORT_SETTING_NAME)) { + return nm_device_hash_check_invalid_keys(diffs, + NM_SETTING_BRIDGE_PORT_SETTING_NAME, + error, + NM_SETTING_BRIDGE_PORT_VLANS); + } + + if (nm_streq(setting_name, NM_SETTING_SRIOV_SETTING_NAME)) { + return nm_device_hash_check_invalid_keys(diffs, + NM_SETTING_SRIOV_SETTING_NAME, + error, + NM_SETTING_SRIOV_PRESERVE_ON_DOWN); } out_fail: @@ -16851,6 +16913,8 @@ _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; @@ -16896,6 +16960,7 @@ 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)); @@ -16918,6 +16983,17 @@ 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); @@ -17437,7 +17513,8 @@ _set_state_full(NMDevice *self, NMDeviceState state, NMDeviceStateReason reason, } if (priv->ifindex > 0 - && (s_sriov = nm_device_get_applied_setting(self, NM_TYPE_SETTING_SRIOV))) { + && (s_sriov = nm_device_get_applied_setting(self, NM_TYPE_SETTING_SRIOV)) + && (!_prop_get_sriov_preserve_on_down(self, s_sriov))) { priv->sriov_reset_pending++; sriov_op_queue(self, 0, @@ -17492,7 +17569,8 @@ _set_state_full(NMDevice *self, NMDeviceState state, NMDeviceStateReason reason, nm_settings_connection_update_timestamp(sett_conn, (guint64) 0); if (priv->ifindex > 0 - && (s_sriov = nm_device_get_applied_setting(self, NM_TYPE_SETTING_SRIOV))) { + && (s_sriov = nm_device_get_applied_setting(self, NM_TYPE_SETTING_SRIOV)) + && (!_prop_get_sriov_preserve_on_down(self, s_sriov))) { priv->sriov_reset_pending++; sriov_op_queue(self, 0, @@ -18613,7 +18691,7 @@ hostname_dns_lookup_callback(GObject *source, GAsyncResult *result, gpointer use gboolean valid; resolver->hostname = g_steal_pointer(&output); - valid = nm_utils_validate_hostname(resolver->hostname); + valid = nm_sd_dns_name_is_valid(resolver->hostname); _LOGD(LOGD_DNS, "hostname-from-dns: ipv%c resolver %s: lookup successful for %s, result %s%s%s%s", @@ -18858,6 +18936,19 @@ 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 9b051ab4..9a663c2a 100644 --- a/src/core/devices/nm-device.h +++ b/src/core/devices/nm-device.h @@ -209,8 +209,6 @@ typedef struct _NMDeviceClass { bool act_stage1_prepare_set_hwaddr_ethernet : 1; - bool can_reapply_change_ovs_external_ids : 1; - bool allow_autoconnect_on_external : 1; NMRfkillType rfkill_type : 4; @@ -854,4 +852,14 @@ 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/nm-lldp-listener.c b/src/core/devices/nm-lldp-listener.c index e08b379a..5c90911f 100644 --- a/src/core/devices/nm-lldp-listener.c +++ b/src/core/devices/nm-lldp-listener.c @@ -310,7 +310,7 @@ format_string(const guint8 *data, gsize len, gboolean allow_trim, char **out_to_ if (len == 0) return NULL; - if (memchr(data, len, '\0')) + if (memchr(data, '\0', len)) return NULL; return nm_utils_buf_utf8safe_escape(data, diff --git a/src/core/devices/ovs/nm-device-ovs-bridge.c b/src/core/devices/ovs/nm-device-ovs-bridge.c index c9b1f4c6..c9736eeb 100644 --- a/src/core/devices/ovs/nm-device-ovs-bridge.c +++ b/src/core/devices/ovs/nm-device-ovs-bridge.c @@ -162,6 +162,11 @@ can_reapply_change(NMDevice *device, NM_SETTING_OVS_BRIDGE_STP_ENABLE); } + if (NM_IN_STRSET(setting_name, + NM_SETTING_OVS_EXTERNAL_IDS_SETTING_NAME, + NM_SETTING_OVS_OTHER_CONFIG_SETTING_NAME)) + return TRUE; + return device_class->can_reapply_change(device, setting_name, s_old, s_new, diffs, error); } @@ -194,16 +199,15 @@ nm_device_ovs_bridge_class_init(NMDeviceOvsBridgeClass *klass) device_class->connection_type_check_compatible = NM_SETTING_OVS_BRIDGE_SETTING_NAME; device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES(); - device_class->is_controller = TRUE; - device_class->get_type_description = get_type_description; - device_class->create_and_realize = create_and_realize; - device_class->unrealize = unrealize; - device_class->get_generic_capabilities = get_generic_capabilities; - device_class->act_stage3_ip_config = act_stage3_ip_config; - device_class->ready_for_ip_config = ready_for_ip_config; - device_class->attach_port = attach_port; - device_class->detach_port = detach_port; - device_class->can_reapply_change = can_reapply_change; - device_class->can_reapply_change_ovs_external_ids = TRUE; - device_class->reapply_connection = nm_device_ovs_reapply_connection; + device_class->is_controller = TRUE; + device_class->get_type_description = get_type_description; + device_class->create_and_realize = create_and_realize; + device_class->unrealize = unrealize; + device_class->get_generic_capabilities = get_generic_capabilities; + device_class->act_stage3_ip_config = act_stage3_ip_config; + device_class->ready_for_ip_config = ready_for_ip_config; + device_class->attach_port = attach_port; + device_class->detach_port = detach_port; + device_class->can_reapply_change = can_reapply_change; + device_class->reapply_connection = nm_device_ovs_reapply_connection; } diff --git a/src/core/devices/ovs/nm-device-ovs-interface.c b/src/core/devices/ovs/nm-device-ovs-interface.c index 512aa5c3..922ed345 100644 --- a/src/core/devices/ovs/nm-device-ovs-interface.c +++ b/src/core/devices/ovs/nm-device-ovs-interface.c @@ -16,6 +16,8 @@ #include "nm-setting-ovs-bridge.h" #include "nm-setting-ovs-interface.h" #include "nm-setting-ovs-port.h" +#include "nm-setting-ovs-external-ids.h" +#include "nm-setting-ovs-other-config.h" #define _NMLOG_DEVICE_TYPE NMDeviceOvsInterface #include "devices/nm-device-logging.h" @@ -631,6 +633,28 @@ can_update_from_platform_link(NMDevice *device, const NMPlatformLink *plink) return !plink || nm_device_get_state(device) != NM_DEVICE_STATE_DEACTIVATING; } +static gboolean +can_reapply_change(NMDevice *device, + const char *setting_name, + NMSetting *s_old, + NMSetting *s_new, + GHashTable *diffs, + GError **error) +{ + NMDeviceClass *device_class = NM_DEVICE_CLASS(nm_device_ovs_interface_parent_class); + + if (NM_IN_STRSET(setting_name, + NM_SETTING_OVS_EXTERNAL_IDS_SETTING_NAME, + NM_SETTING_OVS_OTHER_CONFIG_SETTING_NAME)) { + /* TODO: it's currently not possible to reapply those settings on OVS + * system interfaces because they have type != "ovs-interface" (e.g. + * "ethernet") */ + return TRUE; + } + + return device_class->can_reapply_change(device, setting_name, s_old, s_new, diffs, error); +} + /*****************************************************************************/ static void @@ -696,21 +720,21 @@ nm_device_ovs_interface_class_init(NMDeviceOvsInterfaceClass *klass) device_class->connection_type_check_compatible = NM_SETTING_OVS_INTERFACE_SETTING_NAME; device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES(NM_LINK_TYPE_OPENVSWITCH); - device_class->can_auto_connect = can_auto_connect; - device_class->can_update_from_platform_link = can_update_from_platform_link; - device_class->deactivate = deactivate; - device_class->deactivate_async = deactivate_async; - device_class->get_type_description = get_type_description; - device_class->create_and_realize = create_and_realize; - device_class->get_generic_capabilities = get_generic_capabilities; - device_class->is_available = is_available; - device_class->check_connection_compatible = check_connection_compatible; - device_class->link_changed = link_changed; - device_class->act_stage3_ip_config = act_stage3_ip_config; - device_class->ready_for_ip_config = ready_for_ip_config; - device_class->can_unmanaged_external_down = can_unmanaged_external_down; - device_class->set_platform_mtu = set_platform_mtu; - device_class->get_configured_mtu = nm_device_get_configured_mtu_for_wired; - device_class->can_reapply_change_ovs_external_ids = TRUE; - device_class->reapply_connection = nm_device_ovs_reapply_connection; + device_class->can_auto_connect = can_auto_connect; + device_class->can_update_from_platform_link = can_update_from_platform_link; + device_class->deactivate = deactivate; + device_class->deactivate_async = deactivate_async; + device_class->get_type_description = get_type_description; + device_class->create_and_realize = create_and_realize; + device_class->get_generic_capabilities = get_generic_capabilities; + device_class->is_available = is_available; + device_class->check_connection_compatible = check_connection_compatible; + device_class->link_changed = link_changed; + device_class->act_stage3_ip_config = act_stage3_ip_config; + device_class->ready_for_ip_config = ready_for_ip_config; + device_class->can_unmanaged_external_down = can_unmanaged_external_down; + device_class->set_platform_mtu = set_platform_mtu; + device_class->get_configured_mtu = nm_device_get_configured_mtu_for_wired; + device_class->can_reapply_change = can_reapply_change; + device_class->reapply_connection = nm_device_ovs_reapply_connection; } diff --git a/src/core/devices/ovs/nm-device-ovs-port.c b/src/core/devices/ovs/nm-device-ovs-port.c index e9928548..0e3ef92c 100644 --- a/src/core/devices/ovs/nm-device-ovs-port.c +++ b/src/core/devices/ovs/nm-device-ovs-port.c @@ -16,6 +16,8 @@ #include "nm-setting-connection.h" #include "nm-setting-ovs-port.h" #include "nm-setting-ovs-interface.h" +#include "nm-setting-ovs-external-ids.h" +#include "nm-setting-ovs-other-config.h" #include "nm-setting-wired.h" #define _NMLOG_DEVICE_TYPE NMDeviceOvsPort @@ -279,6 +281,11 @@ can_reapply_change(NMDevice *device, NM_SETTING_OVS_PORT_TRUNKS); } + if (NM_IN_STRSET(setting_name, + NM_SETTING_OVS_EXTERNAL_IDS_SETTING_NAME, + NM_SETTING_OVS_OTHER_CONFIG_SETTING_NAME)) + return TRUE; + return device_class->can_reapply_change(device, setting_name, s_old, s_new, diffs, error); } @@ -311,15 +318,14 @@ nm_device_ovs_port_class_init(NMDeviceOvsPortClass *klass) device_class->connection_type_check_compatible = NM_SETTING_OVS_PORT_SETTING_NAME; device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES(); - device_class->is_controller = TRUE; - device_class->get_type_description = get_type_description; - device_class->create_and_realize = create_and_realize; - device_class->get_generic_capabilities = get_generic_capabilities; - device_class->act_stage3_ip_config = act_stage3_ip_config; - device_class->ready_for_ip_config = ready_for_ip_config; - device_class->attach_port = attach_port; - device_class->detach_port = detach_port; - device_class->can_reapply_change = can_reapply_change; - device_class->can_reapply_change_ovs_external_ids = TRUE; - device_class->reapply_connection = nm_device_ovs_reapply_connection; + device_class->is_controller = TRUE; + device_class->get_type_description = get_type_description; + device_class->create_and_realize = create_and_realize; + device_class->get_generic_capabilities = get_generic_capabilities; + device_class->act_stage3_ip_config = act_stage3_ip_config; + device_class->ready_for_ip_config = ready_for_ip_config; + device_class->attach_port = attach_port; + device_class->detach_port = detach_port; + device_class->can_reapply_change = can_reapply_change; + device_class->reapply_connection = nm_device_ovs_reapply_connection; } diff --git a/src/core/devices/ovs/nm-ovs-factory.c b/src/core/devices/ovs/nm-ovs-factory.c index 2ca1a0b5..4084356f 100644 --- a/src/core/devices/ovs/nm-ovs-factory.c +++ b/src/core/devices/ovs/nm-ovs-factory.c @@ -75,9 +75,6 @@ new_device_from_type(const char *name, NMDeviceType device_type) const char *type_desc; NMLinkType link_type = NM_LINK_TYPE_NONE; - if (nm_manager_get_device(NM_MANAGER_GET, name, device_type)) - return NULL; - if (device_type == NM_DEVICE_TYPE_OVS_INTERFACE) { type = NM_TYPE_DEVICE_OVS_INTERFACE; type_desc = "Open vSwitch Interface"; @@ -89,6 +86,7 @@ new_device_from_type(const char *name, NMDeviceType device_type) type = NM_TYPE_DEVICE_OVS_BRIDGE; type_desc = "Open vSwitch Bridge"; } else { + _LOGT(name, NULL, "Unrecognized link type: %d", device_type); return NULL; } @@ -125,6 +123,11 @@ ovsdb_device_added(NMOvsdb *ovsdb, return; } + if (nm_manager_get_device(NM_MANAGER_GET, name, device_type)) { + _LOGT(name, NULL, "Device already registered with manager, skipping."); + return; + } + device = new_device_from_type(name, device_type); if (!device) return; @@ -288,23 +291,31 @@ create_device(NMDeviceFactory *self, { NMDeviceType device_type = NM_DEVICE_TYPE_UNKNOWN; const char *connection_type = NULL; + const char *connection_uuid = NULL; if (g_strcmp0(iface, "ovs-system") == 0) { *out_ignore = TRUE; return NULL; } - if (connection) + if (connection) { connection_type = nm_connection_get_connection_type(connection); + connection_uuid = nm_connection_get_uuid(connection); + } - if (plink) + if (plink) { + _LOGD(iface, connection_uuid, "creating OVS interface (from a platform link)"); device_type = NM_DEVICE_TYPE_OVS_INTERFACE; - else if (g_strcmp0(connection_type, NM_SETTING_OVS_INTERFACE_SETTING_NAME) == 0) + } else if (nm_streq0(connection_type, NM_SETTING_OVS_INTERFACE_SETTING_NAME)) { + _LOGD(iface, connection_uuid, "creating OVS interface (from setting)"); device_type = NM_DEVICE_TYPE_OVS_INTERFACE; - else if (g_strcmp0(connection_type, NM_SETTING_OVS_PORT_SETTING_NAME) == 0) + } else if (nm_streq0(connection_type, NM_SETTING_OVS_PORT_SETTING_NAME)) { + _LOGD(iface, connection_uuid, "creating OVS port (from setting)"); device_type = NM_DEVICE_TYPE_OVS_PORT; - else if (g_strcmp0(connection_type, NM_SETTING_OVS_BRIDGE_SETTING_NAME) == 0) + } else if (nm_streq0(connection_type, NM_SETTING_OVS_BRIDGE_SETTING_NAME)) { + _LOGD(iface, connection_uuid, "creating OVS bridge (from setting)"); device_type = NM_DEVICE_TYPE_OVS_BRIDGE; + } return new_device_from_type(iface, device_type); } diff --git a/src/core/devices/ovs/nm-ovsdb.c b/src/core/devices/ovs/nm-ovsdb.c index 2dbc842a..164bfd35 100644 --- a/src/core/devices/ovs/nm-ovsdb.c +++ b/src/core/devices/ovs/nm-ovsdb.c @@ -900,15 +900,17 @@ _insert_interface(json_t *params, s_ovs_patch = nm_connection_get_setting_ovs_patch(interface); if (s_ovs_dpdk) { - const char *devargs; - guint32 n_rxq; - guint32 n_rxq_desc; - guint32 n_txq_desc; + const char *devargs; + guint32 n_rxq; + guint32 n_rxq_desc; + guint32 n_txq_desc; + NMSettingOvsDpdkLscInterrupt lsc_int; devargs = nm_setting_ovs_dpdk_get_devargs(s_ovs_dpdk); n_rxq = nm_setting_ovs_dpdk_get_n_rxq(s_ovs_dpdk); n_rxq_desc = nm_setting_ovs_dpdk_get_n_rxq_desc(s_ovs_dpdk); n_txq_desc = nm_setting_ovs_dpdk_get_n_txq_desc(s_ovs_dpdk); + lsc_int = nm_setting_ovs_dpdk_get_lsc_interrupt(s_ovs_dpdk); dpdk_array = json_array(); @@ -930,6 +932,17 @@ _insert_interface(json_t *params, json_pack("[s,s]", "n_txq_desc", nm_sprintf_buf(sbuf, "%u", n_txq_desc))); } + switch (lsc_int) { + case NM_SETTING_OVS_DPDK_LSC_INTERRUPT_IGNORE: + break; + case NM_SETTING_OVS_DPDK_LSC_INTERRUPT_ENABLED: + json_array_append_new(dpdk_array, json_pack("[s,s]", "dpdk-lsc-interrupt", "true")); + break; + case NM_SETTING_OVS_DPDK_LSC_INTERRUPT_DISABLED: + json_array_append_new(dpdk_array, json_pack("[s,s]", "dpdk-lsc-interrupt", "false")); + break; + } + json_array_append_new(options, dpdk_array); } else if (s_ovs_patch) { @@ -1374,88 +1387,113 @@ _delete_interface(NMOvsdb *self, json_t *params, const char *ifname) nm_auto_decref_json json_t *bridges = NULL; nm_auto_decref_json json_t *new_bridges = NULL; gboolean bridges_changed; - gboolean ports_changed; - gboolean interfaces_changed; - int pi; - int ii; bridges = json_array(); new_bridges = json_array(); bridges_changed = FALSE; + /* Loop over all bridges */ g_hash_table_iter_init(&iter, priv->bridges); while (g_hash_table_iter_next(&iter, (gpointer) &ovs_bridge, NULL)) { - nm_auto_decref_json json_t *ports = NULL; - nm_auto_decref_json json_t *new_ports = NULL; + nm_auto_decref_json json_t *ports = NULL; + nm_auto_decref_json json_t *new_ports = NULL; + guint num_nm_ports = 0; + gboolean ports_changed = FALSE; + int pi; - ports = json_array(); - new_ports = json_array(); - ports_changed = FALSE; + ports = json_array(); + new_ports = json_array(); + /* Add the bridge UUID to the list of known bridges for the "expect" condition */ json_array_append_new(bridges, json_pack("[s,s]", "uuid", ovs_bridge->bridge_uuid)); + if (!ovs_bridge->connection_uuid) { + /* Externally created, don't touch it */ + json_array_append_new(new_bridges, json_pack("[s,s]", "uuid", ovs_bridge->bridge_uuid)); + continue; + } + + /* Loop over all bridge's ports */ for (pi = 0; pi < ovs_bridge->ports->len; pi++) { - nm_auto_decref_json json_t *interfaces = NULL; - nm_auto_decref_json json_t *new_interfaces = NULL; + nm_auto_decref_json json_t *interfaces = NULL; + nm_auto_decref_json json_t *new_interfaces = NULL; + guint num_nm_interfaces = 0; + gboolean interfaces_changed = FALSE; + int ii; interfaces = json_array(); new_interfaces = json_array(); port_uuid = g_ptr_array_index(ovs_bridge->ports, pi); ovs_port = g_hash_table_lookup(priv->ports, &port_uuid); + /* Add the port UUID to the list of known bridge port for the "expect" condition */ json_array_append_new(ports, json_pack("[s,s]", "uuid", port_uuid)); - interfaces_changed = FALSE; - if (!ovs_port) { /* This would be a violation of ovsdb's reference integrity (a bug). */ _LOGW("Unknown port '%s' in bridge '%s'", port_uuid, ovs_bridge->bridge_uuid); continue; } + /* Loop over all port's interfaces */ for (ii = 0; ii < ovs_port->interfaces->len; ii++) { interface_uuid = g_ptr_array_index(ovs_port->interfaces, ii); ovs_interface = g_hash_table_lookup(priv->interfaces, &interface_uuid); + /* Add the interface UUID to the list of known port interfaces for the "expect" condition */ json_array_append_new(interfaces, json_pack("[s,s]", "uuid", interface_uuid)); if (ovs_interface) { if (nm_streq(ovs_interface->name, ifname)) { - /* skip the interface */ + /* We are deleting this interface, don't count it */ interfaces_changed = TRUE; continue; } + if (ovs_interface->connection_uuid) + num_nm_interfaces++; } else { /* This would be a violation of ovsdb's reference integrity (a bug). */ _LOGW("Unknown interface '%s' in port '%s'", interface_uuid, port_uuid); } + /* Add the interface to the list of new interfaces to set on the port */ json_array_append_new(new_interfaces, json_pack("[s,s]", "uuid", interface_uuid)); } - if (json_array_size(new_interfaces) == 0) { + 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. */ ports_changed = TRUE; } else { if (interfaces_changed) { + /* An interface needs to be deleted from this port */ _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 (json_array_size(new_ports) == 0) { + 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. */ bridges_changed = TRUE; } else { if (ports_changed) { + /* A port needs to be deleted from this bridge */ _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 */ _expect_ovs_bridges(params, priv->db_uuid, bridges); _set_ovs_bridges(params, priv->db_uuid, new_bridges); } @@ -2211,7 +2249,7 @@ ovsdb_got_update(NMOvsdb *self, json_t *msg) ovs_bridge->connection_uuid, ""), (strtmp1 = _strdict_to_string(ovs_bridge->external_ids)), - (strtmp2 = _strdict_to_string(ovs_bridge->external_ids))); + (strtmp2 = _strdict_to_string(ovs_bridge->other_config))); } } else { gs_free char *strtmp1 = NULL; |