diff options
Diffstat (limited to 'src/core/devices')
| -rw-r--r-- | src/core/devices/bluetooth/nm-device-bt.c | 25 | ||||
| -rw-r--r-- | src/core/devices/nm-device-bond.c | 209 | ||||
| -rw-r--r-- | src/core/devices/nm-device-bridge.c | 148 | ||||
| -rw-r--r-- | src/core/devices/nm-device-veth.c | 15 | ||||
| -rw-r--r-- | src/core/devices/nm-device-vrf.c | 54 | ||||
| -rw-r--r-- | src/core/devices/nm-device-wireguard.c | 2 | ||||
| -rw-r--r-- | src/core/devices/nm-device.c | 582 | ||||
| -rw-r--r-- | src/core/devices/nm-device.h | 19 | ||||
| -rw-r--r-- | src/core/devices/ovs/nm-device-ovs-bridge.c | 18 | ||||
| -rw-r--r-- | src/core/devices/ovs/nm-device-ovs-port.c | 120 | ||||
| -rw-r--r-- | src/core/devices/ovs/nm-ovs-factory.c | 3 | ||||
| -rw-r--r-- | src/core/devices/ovs/nm-ovsdb.c | 11 | ||||
| -rw-r--r-- | src/core/devices/team/nm-device-team.c | 170 | ||||
| -rw-r--r-- | src/core/devices/wifi/nm-device-wifi.c | 30 | ||||
| -rw-r--r-- | src/core/devices/wifi/tests/test-devices-wifi.c | 34 | ||||
| -rw-r--r-- | src/core/devices/wwan/nm-modem-ofono.c | 2 |
16 files changed, 1022 insertions, 420 deletions
diff --git a/src/core/devices/bluetooth/nm-device-bt.c b/src/core/devices/bluetooth/nm-device-bt.c index 39b5c4ec..a8258123 100644 --- a/src/core/devices/bluetooth/nm-device-bt.c +++ b/src/core/devices/bluetooth/nm-device-bt.c @@ -262,6 +262,7 @@ complete_connection(NMDevice *device, const char *ctype; gboolean is_dun = FALSE; gboolean is_pan = FALSE; + gboolean is_nap = FALSE; NMSettingGsm *s_gsm; NMSettingCdma *s_cdma; NMSettingSerial *s_serial; @@ -281,6 +282,8 @@ complete_connection(NMDevice *device, is_dun = TRUE; else if (!strcmp(ctype, NM_SETTING_BLUETOOTH_TYPE_PANU)) is_pan = TRUE; + else if (!strcmp(ctype, NM_SETTING_BLUETOOTH_TYPE_NAP)) + is_nap = TRUE; } else { if (s_gsm || s_cdma) is_dun = TRUE; @@ -288,7 +291,27 @@ complete_connection(NMDevice *device, is_pan = TRUE; } - if (is_pan) { + if (is_nap) { + /* Make sure the device supports NAP */ + if (!(priv->capabilities & NM_BT_CAPABILITY_NAP)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("NAP requested, but Bluetooth device does not support NAP")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_BLUETOOTH_SETTING_NAME, + NM_SETTING_BLUETOOTH_TYPE); + return FALSE; + } + + g_object_set(G_OBJECT(s_bt), + NM_SETTING_BLUETOOTH_TYPE, + NM_SETTING_BLUETOOTH_TYPE_NAP, + NULL); + + fallback_prefix = _("NAP connection"); + } else if (is_pan) { /* Make sure the device supports PAN */ if (!(priv->capabilities & NM_BT_CAPABILITY_NAP)) { g_set_error_literal(error, diff --git a/src/core/devices/nm-device-bond.c b/src/core/devices/nm-device-bond.c index 16896d57..41473abe 100644 --- a/src/core/devices/nm-device-bond.c +++ b/src/core/devices/nm-device-bond.c @@ -9,6 +9,8 @@ #include <stdlib.h> #include <net/if.h> +#include <linux/if_ether.h> +#include <linux/if_link.h> #include "NetworkManagerUtils.h" #include "nm-device-private.h" @@ -16,6 +18,7 @@ #include "nm-device-factory.h" #include "libnm-core-aux-intern/nm-libnm-core-utils.h" #include "libnm-core-intern/nm-core-internal.h" +#include "nm-manager.h" #include "nm-setting-bond-port.h" #define _NMLOG_DEVICE_TYPE NMDeviceBond @@ -312,7 +315,7 @@ set_bond_attr_or_default(NMDevice *device, NMSettingBond *s_bond, const char *op NMDeviceBond *self = NM_DEVICE_BOND(device); const char *value; - value = nm_setting_bond_get_option_or_default(s_bond, opt); + value = nm_setting_bond_get_option_normalized(s_bond, opt); if (!value) { if (_LOGT_ENABLED(LOGD_BOND) && nm_setting_bond_get_option_by_name(s_bond, opt)) _LOGT(LOGD_BOND, "bond option '%s' not set as it conflicts with other options", opt); @@ -346,54 +349,147 @@ set_bond_arp_ip_targets(NMDevice *device, NMSettingBond *s_bond) set_arp_targets( device, cur_arp_ip_target, - nm_setting_bond_get_option_or_default(s_bond, NM_SETTING_BOND_OPTION_ARP_IP_TARGET)); + nm_setting_bond_get_option_normalized(s_bond, NM_SETTING_BOND_OPTION_ARP_IP_TARGET)); } -static gboolean -apply_bonding_config(NMDeviceBond *self) +static guint8 +_bond_arp_ip_target_to_platform(const char *value, in_addr_t out[static NM_BOND_MAX_ARP_TARGETS]) { - NMDevice *device = NM_DEVICE(self); - NMSettingBond *s_bond; - NMBondMode mode; - const char *mode_str; - gs_free char *device_bond_mode = NULL; + gs_free const char **ip = NULL; + in_addr_t in_a; + int i; + int added = 0; - s_bond = nm_device_get_applied_setting(device, NM_TYPE_SETTING_BOND); - g_return_val_if_fail(s_bond, FALSE); + ip = nm_utils_bond_option_arp_ip_targets_split(value); - mode_str = nm_setting_bond_get_option_or_default(s_bond, NM_SETTING_BOND_OPTION_MODE); - mode = _nm_setting_bond_mode_from_string(mode_str); - g_return_val_if_fail(mode != NM_BOND_MODE_UNKNOWN, FALSE); + if (!ip) + return added; - /* Set mode first, as some other options (e.g. arp_interval) are valid - * only for certain modes. - */ - device_bond_mode = nm_platform_sysctl_master_get_option(nm_device_get_platform(device), - nm_device_get_ifindex(device), - NM_SETTING_BOND_OPTION_MODE); - /* Need to release all slaves before we can change bond mode */ - if (!nm_streq0(device_bond_mode, mode_str)) - nm_device_master_release_slaves_all(device); + for (i = 0; ip[i]; i++) { + if (added > NM_BOND_MAX_ARP_TARGETS - 1) + break; + if (!nm_utils_parse_inaddr_bin(AF_INET, ip[i], NULL, &in_a)) + nm_assert_not_reached(); /* verify() already validated the IP addresses */ + + out[added++] = in_a; + } + return added; +} - set_bond_attr_or_default(device, s_bond, NM_SETTING_BOND_OPTION_MODE); +static int +_setting_bond_primary_opt_as_ifindex(NMSettingBond *s_bond) +{ + const char *primary_str; + int ifindex = 0; - set_bond_arp_ip_targets(device, s_bond); + primary_str = nm_setting_bond_get_option_normalized(s_bond, NM_SETTING_BOND_OPTION_PRIMARY); - set_bond_attrs_or_default(device, s_bond, NM_MAKE_STRV(OPTIONS_APPLY_SUBSET)); - return TRUE; + if (primary_str != NULL) + ifindex = nm_platform_link_get_ifindex(NM_PLATFORM_GET, primary_str); + + return ifindex; +} + +static void +_platform_lnk_bond_init_from_setting(NMSettingBond *s_bond, NMPlatformLnkBond *props) +{ + const char *opt_value; + + *props = (NMPlatformLnkBond){ + .mode = _nm_setting_bond_mode_from_string( + nm_setting_bond_get_option_normalized(s_bond, NM_SETTING_BOND_OPTION_MODE)), + .primary = _setting_bond_primary_opt_as_ifindex(s_bond), + .miimon = _nm_setting_bond_opt_value_as_u32(s_bond, NM_SETTING_BOND_OPTION_MIIMON), + .updelay = _nm_setting_bond_opt_value_as_u32(s_bond, NM_SETTING_BOND_OPTION_UPDELAY), + .downdelay = _nm_setting_bond_opt_value_as_u32(s_bond, NM_SETTING_BOND_OPTION_DOWNDELAY), + .arp_interval = + _nm_setting_bond_opt_value_as_u32(s_bond, NM_SETTING_BOND_OPTION_ARP_INTERVAL), + .resend_igmp = + _nm_setting_bond_opt_value_as_u32(s_bond, NM_SETTING_BOND_OPTION_RESEND_IGMP), + .min_links = _nm_setting_bond_opt_value_as_u32(s_bond, NM_SETTING_BOND_OPTION_MIN_LINKS), + .lp_interval = + _nm_setting_bond_opt_value_as_u32(s_bond, NM_SETTING_BOND_OPTION_LP_INTERVAL), + .packets_per_port = + _nm_setting_bond_opt_value_as_u32(s_bond, NM_SETTING_BOND_OPTION_PACKETS_PER_SLAVE), + .peer_notif_delay = + _nm_setting_bond_opt_value_as_u32(s_bond, NM_SETTING_BOND_OPTION_PEER_NOTIF_DELAY), + .arp_all_targets = _nm_setting_bond_arp_all_targets_from_string( + nm_setting_bond_get_option_normalized(s_bond, NM_SETTING_BOND_OPTION_ARP_ALL_TARGETS)), + .arp_validate = _nm_setting_bond_arp_validate_from_string( + nm_setting_bond_get_option_normalized(s_bond, NM_SETTING_BOND_OPTION_ARP_VALIDATE)), + .ad_actor_sys_prio = + _nm_setting_bond_opt_value_as_u16(s_bond, NM_SETTING_BOND_OPTION_AD_ACTOR_SYS_PRIO), + .ad_user_port_key = + _nm_setting_bond_opt_value_as_u16(s_bond, NM_SETTING_BOND_OPTION_AD_USER_PORT_KEY), + .primary_reselect = _nm_setting_bond_primary_reselect_from_string( + nm_setting_bond_get_option_normalized(s_bond, NM_SETTING_BOND_OPTION_PRIMARY_RESELECT)), + .fail_over_mac = _nm_setting_bond_fail_over_mac_from_string( + nm_setting_bond_get_option_normalized(s_bond, NM_SETTING_BOND_OPTION_FAIL_OVER_MAC)), + .xmit_hash_policy = _nm_setting_bond_xmit_hash_policy_from_string( + nm_setting_bond_get_option_normalized(s_bond, NM_SETTING_BOND_OPTION_XMIT_HASH_POLICY)), + .num_grat_arp = + _nm_setting_bond_opt_value_as_u8(s_bond, NM_SETTING_BOND_OPTION_NUM_GRAT_ARP), + .all_ports_active = + _nm_setting_bond_opt_value_as_u8(s_bond, NM_SETTING_BOND_OPTION_ALL_SLAVES_ACTIVE), + .lacp_rate = _nm_setting_bond_lacp_rate_from_string( + nm_setting_bond_get_option_normalized(s_bond, NM_SETTING_BOND_OPTION_LACP_RATE)), + .ad_select = _nm_setting_bond_ad_select_from_string( + nm_setting_bond_get_option_normalized(s_bond, NM_SETTING_BOND_OPTION_AD_SELECT)), + }; + + nm_ether_addr_from_string( + &props->ad_actor_system, + nm_setting_bond_get_option_normalized(s_bond, NM_SETTING_BOND_OPTION_AD_ACTOR_SYSTEM)); + + opt_value = nm_setting_bond_get_option_normalized(s_bond, NM_SETTING_BOND_OPTION_USE_CARRIER); + if (opt_value != NULL) + props->use_carrier = _nm_utils_ascii_str_to_bool(opt_value, FALSE); + + opt_value = + nm_setting_bond_get_option_normalized(s_bond, NM_SETTING_BOND_OPTION_TLB_DYNAMIC_LB); + if (opt_value != NULL) + props->tlb_dynamic_lb = _nm_utils_ascii_str_to_bool(opt_value, FALSE); + + opt_value = nm_setting_bond_get_option_normalized(s_bond, NM_SETTING_BOND_OPTION_ARP_IP_TARGET); + if (opt_value != NULL) + props->arp_ip_targets_num = + _bond_arp_ip_target_to_platform(opt_value, props->arp_ip_target); + + props->miimon_has = !props->arp_interval && !props->arp_validate; + props->updelay_has = props->miimon_has && props->miimon; + props->downdelay_has = props->miimon_has && props->miimon; + props->peer_notif_delay_has = (props->miimon || props->arp_interval) && props->peer_notif_delay; + props->arp_all_targets_has = props->arp_interval && props->arp_all_targets; + props->resend_igmp_has = props->resend_igmp != 1; + props->lp_interval = props->lp_interval != 1; + props->tlb_dynamic_lb_has = NM_IN_SET(props->mode, NM_BOND_MODE_TLB, NM_BOND_MODE_ALB); } static NMActStageReturn act_stage1_prepare(NMDevice *device, NMDeviceStateReason *out_failure_reason) { - NMDeviceBond *self = NM_DEVICE_BOND(device); - NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS; + NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS; + NMConnection *connection; + NMSettingBond *s_bond; + NMPlatformLnkBond props; + int r; + int ifindex = nm_device_get_ifindex(device); + + connection = nm_device_get_applied_connection(device); + g_return_val_if_fail(connection, NM_ACT_STAGE_RETURN_FAILURE); + + s_bond = nm_connection_get_setting_bond(connection); + g_return_val_if_fail(s_bond, NM_ACT_STAGE_RETURN_FAILURE); + + _platform_lnk_bond_init_from_setting(s_bond, &props); /* Interface must be down to set bond options */ nm_device_take_down(device, TRUE); - if (!apply_bonding_config(self)) + r = nm_platform_link_bond_change(nm_device_get_platform(device), ifindex, &props); + if (r < 0) { ret = NM_ACT_STAGE_RETURN_FAILURE; - else { + NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_CONFIG_FAILED); + } else { if (!nm_device_hw_addr_set_cloned(device, nm_device_get_applied_connection(device), FALSE)) ret = NM_ACT_STAGE_RETURN_FAILURE; } @@ -424,8 +520,14 @@ commit_port_options(NMDevice *bond_device, NMDevice *port, NMSettingBondPort *s_ queue_id_str); } -static gboolean -enslave_slave(NMDevice *device, NMDevice *port, NMConnection *connection, gboolean configure) +static NMTernary +attach_port(NMDevice *device, + NMDevice *port, + NMConnection *connection, + gboolean configure, + GCancellable *cancellable, + NMDeviceAttachPortCallback callback, + gpointer user_data) { NMDeviceBond *self = NM_DEVICE_BOND(device); NMSettingBondPort *s_port; @@ -442,7 +544,7 @@ enslave_slave(NMDevice *device, NMDevice *port, NMConnection *connection, gboole nm_device_bring_up(port, TRUE, NULL); if (!success) { - _LOGI(LOGD_BOND, "assigning bond port %s: failed", nm_device_get_ip_iface(port)); + _LOGI(LOGD_BOND, "attaching bond port %s: failed", nm_device_get_ip_iface(port)); return FALSE; } @@ -450,15 +552,15 @@ enslave_slave(NMDevice *device, NMDevice *port, NMConnection *connection, gboole commit_port_options(device, port, s_port); - _LOGI(LOGD_BOND, "assigned bond port %s", nm_device_get_ip_iface(port)); + _LOGI(LOGD_BOND, "attached bond port %s", nm_device_get_ip_iface(port)); } else - _LOGI(LOGD_BOND, "bond port %s was assigned", nm_device_get_ip_iface(port)); + _LOGI(LOGD_BOND, "bond port %s was attached", nm_device_get_ip_iface(port)); return TRUE; } static void -release_slave(NMDevice *device, NMDevice *slave, gboolean configure) +detach_port(NMDevice *device, NMDevice *port, gboolean configure) { NMDeviceBond *self = NM_DEVICE_BOND(device); gboolean success; @@ -472,10 +574,10 @@ release_slave(NMDevice *device, NMDevice *slave, gboolean configure) configure = FALSE; } - ifindex_slave = nm_device_get_ip_ifindex(slave); + ifindex_slave = nm_device_get_ip_ifindex(port); if (ifindex_slave <= 0) - _LOGD(LOGD_BOND, "bond slave %s is already released", nm_device_get_ip_iface(slave)); + _LOGD(LOGD_BOND, "bond port %s is already detached", nm_device_get_ip_iface(port)); if (configure) { NMConnection *applied; @@ -490,9 +592,9 @@ release_slave(NMDevice *device, NMDevice *slave, gboolean configure) ifindex_slave); if (success) { - _LOGI(LOGD_BOND, "released bond slave %s", nm_device_get_ip_iface(slave)); + _LOGI(LOGD_BOND, "detached bond port %s", nm_device_get_ip_iface(port)); } else { - _LOGW(LOGD_BOND, "failed to release bond slave %s", nm_device_get_ip_iface(slave)); + _LOGW(LOGD_BOND, "failed to detach bond port %s", nm_device_get_ip_iface(port)); } } @@ -512,12 +614,12 @@ release_slave(NMDevice *device, NMDevice *slave, gboolean configure) * other state is noticed by the now-released slave. */ if (ifindex_slave > 0) { - if (!nm_device_bring_up(slave, TRUE, NULL)) - _LOGW(LOGD_BOND, "released bond slave could not be brought up."); + if (!nm_device_bring_up(port, TRUE, NULL)) + _LOGW(LOGD_BOND, "detached bond port could not be brought up."); } } else { if (ifindex_slave > 0) { - _LOGI(LOGD_BOND, "bond slave %s was released", nm_device_get_ip_iface(slave)); + _LOGI(LOGD_BOND, "bond port %s was detached", nm_device_get_ip_iface(port)); } } } @@ -529,12 +631,19 @@ create_and_realize(NMDevice *device, const NMPlatformLink **out_plink, GError **error) { - const char *iface = nm_device_get_iface(device); - int r; + const char *iface = nm_device_get_iface(device); + NMSettingBond *s_bond; + NMPlatformLnkBond props; + int r; g_assert(iface); - r = nm_platform_link_bond_add(nm_device_get_platform(device), iface, out_plink); + s_bond = nm_connection_get_setting_bond(connection); + nm_assert(s_bond); + + _platform_lnk_bond_init_from_setting(s_bond, &props); + + r = nm_platform_link_bond_add(nm_device_get_platform(device), iface, &props, out_plink); if (r < 0) { g_set_error(error, NM_DEVICE_ERROR, @@ -612,7 +721,7 @@ reapply_connection(NMDevice *device, NMConnection *con_old, NMConnection *con_ne s_bond = nm_connection_get_setting_bond(con_new); g_return_if_fail(s_bond); - value = nm_setting_bond_get_option_or_default(s_bond, NM_SETTING_BOND_OPTION_MODE); + value = nm_setting_bond_get_option_normalized(s_bond, NM_SETTING_BOND_OPTION_MODE); mode = _nm_setting_bond_mode_from_string(value); g_return_if_fail(mode != NM_BOND_MODE_UNKNOWN); @@ -663,8 +772,8 @@ nm_device_bond_class_init(NMDeviceBondClass *klass) device_class->create_and_realize = create_and_realize; device_class->act_stage1_prepare = act_stage1_prepare; device_class->get_configured_mtu = nm_device_get_configured_mtu_for_wired; - device_class->enslave_slave = enslave_slave; - device_class->release_slave = release_slave; + device_class->attach_port = attach_port; + device_class->detach_port = detach_port; device_class->can_reapply_change = can_reapply_change; device_class->reapply_connection = reapply_connection; } diff --git a/src/core/devices/nm-device-bridge.c b/src/core/devices/nm-device-bridge.c index 9bf7ac01..31cf361e 100644 --- a/src/core/devices/nm-device-bridge.c +++ b/src/core/devices/nm-device-bridge.c @@ -836,30 +836,33 @@ _platform_lnk_bridge_init_from_setting(NMSettingBridge *s_bridge, NMPlatformLnkB to_sysfs_group_address_sys(nm_setting_bridge_get_group_address(s_bridge), &props->group_addr); } -static NMActStageReturn -act_stage1_prepare(NMDevice *device, NMDeviceStateReason *out_failure_reason) +static gboolean +link_config(NMDevice *device, NMConnection *connection) { - NMConnection *connection; + int ifindex = nm_device_get_ifindex(device); NMSettingBridge *s_bridge; NMPlatformLnkBridge props; - int r; - int ifindex = nm_device_get_ifindex(device); - - connection = nm_device_get_applied_connection(device); - g_return_val_if_fail(connection, NM_ACT_STAGE_RETURN_FAILURE); s_bridge = nm_connection_get_setting_bridge(connection); - g_return_val_if_fail(s_bridge, NM_ACT_STAGE_RETURN_FAILURE); + g_return_val_if_fail(s_bridge, FALSE); _platform_lnk_bridge_init_from_setting(s_bridge, &props); - r = nm_platform_link_bridge_change(nm_device_get_platform(device), ifindex, &props); - if (r < 0) { - NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_CONFIG_FAILED); - return NM_ACT_STAGE_RETURN_FAILURE; - } + if (nm_platform_link_bridge_change(nm_device_get_platform(device), ifindex, &props) < 0) + return FALSE; + + return bridge_set_vlan_options(device, s_bridge); +} + +static NMActStageReturn +act_stage1_prepare(NMDevice *device, NMDeviceStateReason *out_failure_reason) +{ + NMConnection *connection; + + connection = nm_device_get_applied_connection(device); + g_return_val_if_fail(connection, NM_ACT_STAGE_RETURN_FAILURE); - if (!bridge_set_vlan_options(device, s_bridge)) { + if (!link_config(device, connection)) { NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_CONFIG_FAILED); return NM_ACT_STAGE_RETURN_FAILURE; } @@ -974,8 +977,14 @@ deactivate(NMDevice *device) } } -static gboolean -enslave_slave(NMDevice *device, NMDevice *slave, NMConnection *connection, gboolean configure) +static NMTernary +attach_port(NMDevice *device, + NMDevice *port, + NMConnection *connection, + gboolean configure, + GCancellable *cancellable, + NMDeviceAttachPortCallback callback, + gpointer user_data) { NMDeviceBridge *self = NM_DEVICE_BRIDGE(device); NMConnection *master_connection; @@ -985,7 +994,7 @@ enslave_slave(NMDevice *device, NMDevice *slave, NMConnection *connection, gbool if (configure) { if (!nm_platform_link_enslave(nm_device_get_platform(device), nm_device_get_ip_ifindex(device), - nm_device_get_ip_ifindex(slave))) + nm_device_get_ip_ifindex(port))) return FALSE; master_connection = nm_device_get_applied_connection(device); @@ -1010,25 +1019,25 @@ enslave_slave(NMDevice *device, NMDevice *slave, NMConnection *connection, gbool * (except for the default one) and so there's no need to flush. */ if (plat_vlans - && !nm_platform_link_set_bridge_vlans(nm_device_get_platform(slave), - nm_device_get_ifindex(slave), + && !nm_platform_link_set_bridge_vlans(nm_device_get_platform(port), + nm_device_get_ifindex(port), TRUE, plat_vlans)) return FALSE; } - commit_slave_options(slave, s_port); + commit_slave_options(port, s_port); - _LOGI(LOGD_BRIDGE, "attached bridge port %s", nm_device_get_ip_iface(slave)); + _LOGI(LOGD_BRIDGE, "attached bridge port %s", nm_device_get_ip_iface(port)); } else { - _LOGI(LOGD_BRIDGE, "bridge port %s was attached", nm_device_get_ip_iface(slave)); + _LOGI(LOGD_BRIDGE, "bridge port %s was attached", nm_device_get_ip_iface(port)); } return TRUE; } static void -release_slave(NMDevice *device, NMDevice *slave, gboolean configure) +detach_port(NMDevice *device, NMDevice *port, gboolean configure) { NMDeviceBridge *self = NM_DEVICE_BRIDGE(device); gboolean success; @@ -1041,10 +1050,10 @@ release_slave(NMDevice *device, NMDevice *slave, gboolean configure) configure = FALSE; } - ifindex_slave = nm_device_get_ip_ifindex(slave); + ifindex_slave = nm_device_get_ip_ifindex(port); if (ifindex_slave <= 0) { - _LOGD(LOGD_TEAM, "bond slave %s is already released", nm_device_get_ip_iface(slave)); + _LOGD(LOGD_TEAM, "bridge port %s is already detached", nm_device_get_ip_iface(port)); return; } @@ -1054,12 +1063,12 @@ release_slave(NMDevice *device, NMDevice *slave, gboolean configure) ifindex_slave); if (success) { - _LOGI(LOGD_BRIDGE, "detached bridge port %s", nm_device_get_ip_iface(slave)); + _LOGI(LOGD_BRIDGE, "detached bridge port %s", nm_device_get_ip_iface(port)); } else { - _LOGW(LOGD_BRIDGE, "failed to detach bridge port %s", nm_device_get_ip_iface(slave)); + _LOGW(LOGD_BRIDGE, "failed to detach bridge port %s", nm_device_get_ip_iface(port)); } } else { - _LOGI(LOGD_BRIDGE, "bridge port %s was detached", nm_device_get_ip_iface(slave)); + _LOGI(LOGD_BRIDGE, "bridge port %s was detached", nm_device_get_ip_iface(port)); } } @@ -1085,10 +1094,6 @@ create_and_realize(NMDevice *device, s_bridge = nm_connection_get_setting_bridge(connection); nm_assert(s_bridge); - s_wired = nm_connection_get_setting_wired(connection); - if (s_wired) - mtu = nm_setting_wired_get_mtu(s_wired); - hwaddr = nm_setting_bridge_get_mac_address(s_bridge); if (!hwaddr && nm_device_hw_addr_get_cloned(device, connection, FALSE, &hwaddr_cloned, NULL, NULL)) { @@ -1113,6 +1118,11 @@ create_and_realize(NMDevice *device, _platform_lnk_bridge_init_from_setting(s_bridge, &props); + s_wired = nm_connection_get_setting_wired(connection); + nm_assert(s_wired); + + mtu = nm_setting_wired_get_mtu(s_wired); + /* If mtu != 0, we set the MTU of the new bridge at creation time. However, kernel will still * automatically adjust the MTU of the bridge based on the minimum of the slave's MTU. * We don't want this automatism as the user asked for a fixed MTU. @@ -1142,6 +1152,72 @@ create_and_realize(NMDevice *device, /*****************************************************************************/ +static gboolean +can_reapply_change(NMDevice *device, + const char *setting_name, + NMSetting *s_old, + NMSetting *s_new, + GHashTable *diffs, + GError **error) +{ + /* Delegate changes to other settings to parent class */ + if (!nm_streq(setting_name, NM_SETTING_BRIDGE_SETTING_NAME)) { + return NM_DEVICE_CLASS(nm_device_bridge_parent_class) + ->can_reapply_change(device, setting_name, s_old, s_new, diffs, error); + } + + return nm_device_hash_check_invalid_keys(diffs, + NM_SETTING_BRIDGE_SETTING_NAME, + error, + NM_SETTING_BRIDGE_STP, + NM_SETTING_BRIDGE_PRIORITY, + NM_SETTING_BRIDGE_FORWARD_DELAY, + NM_SETTING_BRIDGE_HELLO_TIME, + NM_SETTING_BRIDGE_MAX_AGE, + NM_SETTING_BRIDGE_AGEING_TIME, + NM_SETTING_BRIDGE_GROUP_FORWARD_MASK, + NM_SETTING_BRIDGE_MULTICAST_HASH_MAX, + NM_SETTING_BRIDGE_MULTICAST_LAST_MEMBER_COUNT, + NM_SETTING_BRIDGE_MULTICAST_LAST_MEMBER_INTERVAL, + NM_SETTING_BRIDGE_MULTICAST_MEMBERSHIP_INTERVAL, + NM_SETTING_BRIDGE_MULTICAST_SNOOPING, + NM_SETTING_BRIDGE_MULTICAST_ROUTER, + NM_SETTING_BRIDGE_MULTICAST_QUERIER, + NM_SETTING_BRIDGE_MULTICAST_QUERIER_INTERVAL, + NM_SETTING_BRIDGE_MULTICAST_QUERY_INTERVAL, + NM_SETTING_BRIDGE_MULTICAST_QUERY_RESPONSE_INTERVAL, + NM_SETTING_BRIDGE_MULTICAST_QUERY_USE_IFADDR, + NM_SETTING_BRIDGE_MULTICAST_STARTUP_QUERY_COUNT, + NM_SETTING_BRIDGE_MULTICAST_STARTUP_QUERY_INTERVAL, + NM_SETTING_BRIDGE_GROUP_ADDRESS, + NM_SETTING_BRIDGE_VLAN_PROTOCOL, + NM_SETTING_BRIDGE_VLAN_STATS_ENABLED, + NM_SETTING_BRIDGE_VLAN_FILTERING, + NM_SETTING_BRIDGE_VLAN_DEFAULT_PVID, + NM_SETTING_BRIDGE_VLANS); +} + +static void +reapply_connection(NMDevice *device, NMConnection *con_old, NMConnection *con_new) +{ + NMDeviceBridge *self = NM_DEVICE_BRIDGE(device); + NMSettingBridge *s_bridge; + + NM_DEVICE_CLASS(nm_device_bridge_parent_class)->reapply_connection(device, con_old, con_new); + + _LOGD(LOGD_BRIDGE, "reapplying bridge settings"); + s_bridge = nm_connection_get_setting_bridge(con_new); + g_return_if_fail(s_bridge); + + /* Make sure bridge_set_vlan_options() called by link_config() + * sets vlan_filtering and default_pvid anew. */ + self->vlan_configured = FALSE; + + link_config(device, con_new); +} + +/*****************************************************************************/ + static void nm_device_bridge_init(NMDeviceBridge *self) { @@ -1183,9 +1259,11 @@ nm_device_bridge_class_init(NMDeviceBridgeClass *klass) device_class->act_stage1_prepare = act_stage1_prepare; device_class->act_stage2_config = act_stage2_config; device_class->deactivate = deactivate; - device_class->enslave_slave = enslave_slave; - device_class->release_slave = release_slave; + device_class->attach_port = attach_port; + device_class->detach_port = detach_port; device_class->get_configured_mtu = nm_device_get_configured_mtu_for_wired; + device_class->can_reapply_change = can_reapply_change; + device_class->reapply_connection = reapply_connection; } /*****************************************************************************/ diff --git a/src/core/devices/nm-device-veth.c b/src/core/devices/nm-device-veth.c index 8c95a293..63dfd8bb 100644 --- a/src/core/devices/nm-device-veth.c +++ b/src/core/devices/nm-device-veth.c @@ -82,6 +82,8 @@ create_and_realize(NMDevice *device, GError **error) { const char *iface = nm_device_get_iface(device); + const char *peer; + NMDevice *peer_device; NMSettingVeth *s_veth; int r; @@ -96,10 +98,15 @@ create_and_realize(NMDevice *device, return FALSE; } - r = nm_platform_link_veth_add(nm_device_get_platform(device), - iface, - nm_setting_veth_get_peer(s_veth), - out_plink); + peer = nm_setting_veth_get_peer(s_veth); + peer_device = nm_manager_get_device(NM_MANAGER_GET, peer, NM_DEVICE_TYPE_VETH); + if (peer_device) { + /* The veth device and its peer already exist. No need to create it again. */ + if (nm_streq0(nm_device_get_iface(nm_device_parent_get_device(peer_device)), iface)) + return TRUE; + } + + r = nm_platform_link_veth_add(nm_device_get_platform(device), iface, peer, out_plink); if (r < 0) { g_set_error(error, NM_DEVICE_ERROR, diff --git a/src/core/devices/nm-device-vrf.c b/src/core/devices/nm-device-vrf.c index ae80e1d4..2aef0e3d 100644 --- a/src/core/devices/nm-device-vrf.c +++ b/src/core/devices/nm-device-vrf.c @@ -206,38 +206,44 @@ update_connection(NMDevice *device, NMConnection *connection) g_object_set(G_OBJECT(s_vrf), NM_SETTING_VRF_TABLE, priv->props.table, NULL); } -static gboolean -enslave_slave(NMDevice *device, NMDevice *slave, NMConnection *connection, gboolean configure) +static NMTernary +attach_port(NMDevice *device, + NMDevice *port, + NMConnection *connection, + gboolean configure, + GCancellable *cancellable, + NMDeviceAttachPortCallback callback, + gpointer user_data) { - NMDeviceVrf *self = NM_DEVICE_VRF(device); - gboolean success = TRUE; - const char *slave_iface = nm_device_get_ip_iface(slave); + NMDeviceVrf *self = NM_DEVICE_VRF(device); + gboolean success = TRUE; + const char *port_iface = nm_device_get_ip_iface(port); - nm_device_master_check_slave_physical_port(device, slave, LOGD_DEVICE); + nm_device_master_check_slave_physical_port(device, port, LOGD_DEVICE); if (configure) { - nm_device_take_down(slave, TRUE); + nm_device_take_down(port, TRUE); success = nm_platform_link_enslave(nm_device_get_platform(device), nm_device_get_ip_ifindex(device), - nm_device_get_ip_ifindex(slave)); - nm_device_bring_up(slave, TRUE, NULL); + nm_device_get_ip_ifindex(port)); + nm_device_bring_up(port, TRUE, NULL); if (!success) return FALSE; - _LOGI(LOGD_DEVICE, "enslaved VRF slave %s", slave_iface); + _LOGI(LOGD_DEVICE, "attached VRF port %s", port_iface); } else - _LOGI(LOGD_BOND, "VRF slave %s was enslaved", slave_iface); + _LOGI(LOGD_BOND, "VRF port %s was attached", port_iface); return TRUE; } static void -release_slave(NMDevice *device, NMDevice *slave, gboolean configure) +detach_port(NMDevice *device, NMDevice *port, gboolean configure) { NMDeviceVrf *self = NM_DEVICE_VRF(device); gboolean success; - int ifindex_slave; + int ifindex_port; int ifindex; if (configure) { @@ -246,26 +252,26 @@ release_slave(NMDevice *device, NMDevice *slave, gboolean configure) configure = FALSE; } - ifindex_slave = nm_device_get_ip_ifindex(slave); + ifindex_port = nm_device_get_ip_ifindex(port); - if (ifindex_slave <= 0) - _LOGD(LOGD_DEVICE, "VRF slave %s is already released", nm_device_get_ip_iface(slave)); + if (ifindex_port <= 0) + _LOGD(LOGD_DEVICE, "VRF port %s is already detached", nm_device_get_ip_iface(port)); if (configure) { - if (ifindex_slave > 0) { + if (ifindex_port > 0) { success = nm_platform_link_release(nm_device_get_platform(device), nm_device_get_ip_ifindex(device), - ifindex_slave); + ifindex_port); if (success) { - _LOGI(LOGD_DEVICE, "released VRF slave %s", nm_device_get_ip_iface(slave)); + _LOGI(LOGD_DEVICE, "detached VRF port %s", nm_device_get_ip_iface(port)); } else { - _LOGW(LOGD_DEVICE, "failed to release VRF slave %s", nm_device_get_ip_iface(slave)); + _LOGW(LOGD_DEVICE, "failed to detach VRF port %s", nm_device_get_ip_iface(port)); } } } else { - if (ifindex_slave > 0) { - _LOGI(LOGD_DEVICE, "VRF slave %s was released", nm_device_get_ip_iface(slave)); + if (ifindex_port > 0) { + _LOGI(LOGD_DEVICE, "VRF port %s was detached", nm_device_get_ip_iface(port)); } } } @@ -316,8 +322,8 @@ nm_device_vrf_class_init(NMDeviceVrfClass *klass) device_class->is_master = TRUE; device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES(NM_LINK_TYPE_VRF); - device_class->enslave_slave = enslave_slave; - device_class->release_slave = release_slave; + device_class->attach_port = attach_port; + device_class->detach_port = detach_port; device_class->link_changed = link_changed; device_class->unrealize_notify = unrealize_notify; device_class->create_and_realize = create_and_realize; diff --git a/src/core/devices/nm-device-wireguard.c b/src/core/devices/nm-device-wireguard.c index bdb96cb2..179c2a22 100644 --- a/src/core/devices/nm-device-wireguard.c +++ b/src/core/devices/nm-device-wireguard.c @@ -18,7 +18,7 @@ #include "nm-device-private.h" #include "libnm-platform/nm-platform.h" #include "libnm-platform/nmp-object.h" -#include "libnm-platform/nmp-route-manager.h" +#include "libnm-platform/nmp-global-tracker.h" #include "nm-device-factory.h" #include "nm-active-connection.h" #include "nm-act-request.h" diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c index 6b854517..c51da9ac 100644 --- a/src/core/devices/nm-device.c +++ b/src/core/devices/nm-device.c @@ -41,7 +41,7 @@ #include "libnm-platform/nm-platform.h" #include "libnm-platform/nm-platform-utils.h" #include "libnm-platform/nmp-object.h" -#include "libnm-platform/nmp-route-manager.h" +#include "libnm-platform/nmp-global-tracker.h" #include "ndisc/nm-ndisc.h" #include "ndisc/nm-lndp-ndisc.h" @@ -120,11 +120,12 @@ typedef enum _nm_packed { } AddrMethodState; typedef struct { - CList lst_slave; - NMDevice *slave; - gulong watch_id; - bool slave_is_enslaved; - bool configure; + CList lst_slave; + NMDevice *slave; + GCancellable *cancellable; + gulong watch_id; + bool slave_is_enslaved; + bool configure; } SlaveInfo; typedef struct { @@ -392,6 +393,8 @@ typedef struct _NMDevicePrivate { guint device_link_changed_id; guint device_ip_link_changed_id; + GSource *delay_activation_source; + NMDeviceState state; NMDeviceStateReason state_reason; struct { @@ -604,6 +607,7 @@ typedef struct _NMDevicePrivate { const NMDeviceIPState state; NMDeviceIPState state_; }; + gulong dnsmgr_update_pending_signal_id; } ip_data; union { @@ -1394,6 +1398,56 @@ _prop_get_connection_dns_over_tls(NMDevice *self) NM_SETTING_CONNECTION_DNS_OVER_TLS_DEFAULT); } +static NMMptcpFlags +_prop_get_connection_mptcp_flags(NMDevice *self) +{ + NMConnection *connection; + NMMptcpFlags mptcp_flags = NM_MPTCP_FLAGS_NONE; + + g_return_val_if_fail(NM_IS_DEVICE(self), NM_MPTCP_FLAGS_DISABLED); + + connection = nm_device_get_applied_connection(self); + if (connection) { + mptcp_flags = + nm_setting_connection_get_mptcp_flags(nm_connection_get_setting_connection(connection)); + if (mptcp_flags != NM_MPTCP_FLAGS_NONE) + mptcp_flags = nm_mptcp_flags_normalize(mptcp_flags); + } + + if (mptcp_flags == NM_MPTCP_FLAGS_NONE) { + guint64 v; + + v = nm_config_data_get_connection_default_int64(NM_CONFIG_GET_DATA, + NM_CON_DEFAULT("connection.mptcp-flags"), + self, + 0, + G_MAXINT64, + NM_MPTCP_FLAGS_NONE); + /* We filter out all invalid settings and accept it. Somewhat intentionally, we don't do a + * strict parsing of the value to support forward compatibility. */ + if (v != NM_MPTCP_FLAGS_NONE) + mptcp_flags = nm_mptcp_flags_normalize(v); + } + + if (mptcp_flags == NM_MPTCP_FLAGS_NONE) { + gint32 v; + + v = nm_platform_sysctl_get_int32(nm_device_get_platform(self), + NMP_SYSCTL_PATHID_ABSOLUTE("/proc/sys/net/mptcp/enabled"), + -1); + if (v > 0) { + /* if MPTCP is enabled via the sysctl, we use the default. */ + mptcp_flags = _NM_MPTCP_FLAGS_DEFAULT; + } else + mptcp_flags = NM_MPTCP_FLAGS_DISABLED; + } + + nm_assert(mptcp_flags != NM_MPTCP_FLAGS_NONE + && mptcp_flags == nm_mptcp_flags_normalize(mptcp_flags)); + + return mptcp_flags; +} + static guint32 _prop_get_ipvx_route_table(NMDevice *self, int addr_family) { @@ -1508,6 +1562,53 @@ _prop_get_connection_lldp(NMDevice *self) return lldp == NM_SETTING_CONNECTION_LLDP_ENABLE_RX; } +static NMSettingIP4LinkLocal +_prop_get_ipv4_link_local(NMDevice *self) +{ + NMSettingIP4Config *s_ip4; + NMSettingIP4LinkLocal link_local; + + s_ip4 = nm_device_get_applied_setting(self, NM_TYPE_SETTING_IP4_CONFIG); + if (!s_ip4) + return NM_SETTING_IP4_LL_DISABLED; + + link_local = nm_setting_ip4_config_get_link_local(s_ip4); + + if (link_local == NM_SETTING_IP4_LL_DEFAULT) { + /* For connections without a ipv4.link-local property configured the global configuration + might defines the default value for ipv4.link-local. */ + link_local = nm_config_data_get_connection_default_int64(NM_CONFIG_GET_DATA, + NM_CON_DEFAULT("ipv4.link-local"), + self, + NM_SETTING_IP4_LL_AUTO, + NM_SETTING_IP4_LL_ENABLED, + NM_SETTING_IP4_LL_DEFAULT); + if (link_local == NM_SETTING_IP4_LL_DEFAULT) { + /* If there is no global configuration for ipv4.link-local assume auto */ + link_local = NM_SETTING_IP4_LL_AUTO; + } else if (link_local == NM_SETTING_IP4_LL_ENABLED + && nm_streq(nm_setting_ip_config_get_method((NMSettingIPConfig *) s_ip4), + NM_SETTING_IP4_CONFIG_METHOD_DISABLED)) { + /* ipv4.method=disabled has higher priority than the global ipv4.link-local=enabled */ + link_local = NM_SETTING_IP4_LL_DISABLED; + } else if (link_local == NM_SETTING_IP4_LL_DISABLED + && nm_streq(nm_setting_ip_config_get_method((NMSettingIPConfig *) s_ip4), + NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL)) { + /* ipv4.method=link-local has higher priority than the global ipv4.link-local=disabled */ + link_local = NM_SETTING_IP4_LL_ENABLED; + } + } + + if (link_local == NM_SETTING_IP4_LL_AUTO) { + link_local = nm_streq(nm_setting_ip_config_get_method((NMSettingIPConfig *) s_ip4), + NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL) + ? NM_SETTING_IP4_LL_ENABLED + : NM_SETTING_IP4_LL_DISABLED; + } + + return link_local; +} + static guint32 _prop_get_ipv4_dad_timeout(NMDevice *self) { @@ -2118,6 +2219,50 @@ _prop_get_ipv6_ip6_privacy(NMDevice *self) return _ip6_privacy_clamp(ip6_privacy); } +static NMSettingIP6ConfigAddrGenMode +_prop_get_ipv6_addr_gen_mode(NMDevice *self) +{ + NMSettingIP6ConfigAddrGenMode addr_gen_mode; + NMSettingIP6Config *s_ip6; + gint64 c; + + g_return_val_if_fail(self, NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY); + + s_ip6 = nm_device_get_applied_setting(self, NM_TYPE_SETTING_IP6_CONFIG); + if (s_ip6) { + addr_gen_mode = nm_setting_ip6_config_get_addr_gen_mode(s_ip6); + if (NM_IN_SET(addr_gen_mode, + NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64, + NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY)) + return addr_gen_mode; + } else + addr_gen_mode = NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_DEFAULT; + + nm_assert(NM_IN_SET(addr_gen_mode, + NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_DEFAULT_OR_EUI64, + NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_DEFAULT)); + + c = nm_config_data_get_connection_default_int64(NM_CONFIG_GET_DATA, + NM_CON_DEFAULT("ipv6.addr-gen-mode"), + self, + NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64, + NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_DEFAULT, + -1); + if (c != -1) + addr_gen_mode = c; + + if (addr_gen_mode == NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_DEFAULT) + addr_gen_mode = NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY; + else if (addr_gen_mode == NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_DEFAULT_OR_EUI64) + addr_gen_mode = NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64; + + nm_assert(NM_IN_SET(addr_gen_mode, + NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64, + NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY)); + + return addr_gen_mode; +} + static const char * _prop_get_x_cloned_mac_address(NMDevice *self, NMConnection *connection, gboolean is_wifi) { @@ -2678,6 +2823,7 @@ nm_device_create_l3_config_data_from_connection(NMDevice *self, NMConnection *co nm_l3_config_data_set_llmnr(l3cd, _prop_get_connection_llmnr(self)); nm_l3_config_data_set_dns_over_tls(l3cd, _prop_get_connection_dns_over_tls(self)); nm_l3_config_data_set_ip6_privacy(l3cd, _prop_get_ipv6_ip6_privacy(self)); + nm_l3_config_data_set_mptcp_flags(l3cd, _prop_get_connection_mptcp_flags(self)); return l3cd; } @@ -2930,6 +3076,13 @@ _add_capabilities(NMDevice *self, NMDeviceCapabilities capabilities) /*****************************************************************************/ static void +_dev_ip_state_dnsmgr_update_pending_changed(NMDnsManager *dnsmgr, GParamSpec *pspec, NMDevice *self) +{ + _dev_ip_state_check(self, AF_INET); + _dev_ip_state_check(self, AF_INET6); +} + +static void _dev_ip_state_req_timeout_cancel(NMDevice *self, int addr_family) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); @@ -3321,6 +3474,27 @@ got_ip_state: combinedip_state = priv->ip_data.state; } + if (combinedip_state == NM_DEVICE_IP_STATE_READY + && priv->ip_data.state <= NM_DEVICE_IP_STATE_PENDING + && nm_dns_manager_get_update_pending(nm_manager_get_dns_manager(priv->manager))) { + /* We would be ready, but a DNS update is pending. That prevents us from getting fully ready. */ + if (priv->ip_data.dnsmgr_update_pending_signal_id == 0) { + priv->ip_data.dnsmgr_update_pending_signal_id = + g_signal_connect(nm_manager_get_dns_manager(priv->manager), + "notify::" NM_DNS_MANAGER_UPDATE_PENDING, + G_CALLBACK(_dev_ip_state_dnsmgr_update_pending_changed), + self); + _LOGT_ip(AF_UNSPEC, + "check-state: (combined) state: wait for DNS before becoming ready"); + } + combinedip_state = NM_DEVICE_IP_STATE_PENDING; + } + if (combinedip_state != NM_DEVICE_IP_STATE_PENDING + && priv->ip_data.dnsmgr_update_pending_signal_id != 0) { + nm_clear_g_signal_handler(nm_manager_get_dns_manager(priv->manager), + &priv->ip_data.dnsmgr_update_pending_signal_id); + } + _LOGT_ip(AF_UNSPEC, "check-state: (combined) state %s => %s", nm_device_ip_state_to_string(priv->ip_data.state), @@ -5896,43 +6070,16 @@ find_slave_info(NMDevice *self, NMDevice *slave) return NULL; } -/** - * nm_device_master_enslave_slave: - * @self: the master device - * @slave: the slave device to enslave - * @connection: (allow-none): the slave device's connection - * - * If @self is capable of enslaving other devices (ie it's a bridge, bond, team, - * etc) then this function enslaves @slave. - * - * Returns: %TRUE on success, %FALSE on failure or if this device cannot enslave - * other devices. - */ -static gboolean -nm_device_master_enslave_slave(NMDevice *self, NMDevice *slave, NMConnection *connection) +static void +attach_port_done(NMDevice *self, NMDevice *slave, gboolean success) { SlaveInfo *info; - gboolean success = FALSE; - gboolean configure; - - g_return_val_if_fail(self != NULL, FALSE); - g_return_val_if_fail(slave != NULL, FALSE); - g_return_val_if_fail(NM_DEVICE_GET_CLASS(self)->enslave_slave != NULL, FALSE); info = find_slave_info(self, slave); if (!info) - return FALSE; + return; - if (info->slave_is_enslaved) - success = TRUE; - else { - configure = (info->configure && connection != NULL); - if (configure) - g_return_val_if_fail(nm_device_get_state(slave) >= NM_DEVICE_STATE_DISCONNECTED, FALSE); - - success = NM_DEVICE_GET_CLASS(self)->enslave_slave(self, slave, connection, configure); - info->slave_is_enslaved = success; - } + info->slave_is_enslaved = success; nm_device_slave_notify_enslave(info->slave, success); @@ -5952,8 +6099,71 @@ nm_device_master_enslave_slave(NMDevice *self, NMDevice *slave, NMConnection *co */ if (success) nm_device_activate_schedule_stage3_ip_config(self, FALSE); +} - return success; +static void +attach_port_cb(NMDevice *self, GError *error, gpointer user_data) +{ + NMDevice *slave = user_data; + SlaveInfo *info; + + if (nm_utils_error_is_cancelled(error)) + return; + + info = find_slave_info(self, slave); + if (!info) + return; + + nm_clear_g_cancellable(&info->cancellable); + attach_port_done(self, slave, !error); +} + +/** + * nm_device_master_enslave_slave: + * @self: the master device + * @slave: the slave device to enslave + * @connection: (allow-none): the slave device's connection + * + * If @self is capable of enslaving other devices (ie it's a bridge, bond, team, + * etc) then this function enslaves @slave. + */ +static void +nm_device_master_enslave_slave(NMDevice *self, NMDevice *slave, NMConnection *connection) +{ + SlaveInfo *info; + NMTernary success; + gboolean configure; + + g_return_if_fail(self); + g_return_if_fail(slave); + g_return_if_fail(NM_DEVICE_GET_CLASS(self)->attach_port); + + info = find_slave_info(self, slave); + if (!info) + return; + + if (info->slave_is_enslaved) + success = TRUE; + else { + configure = (info->configure && connection != NULL); + if (configure) + g_return_if_fail(nm_device_get_state(slave) >= NM_DEVICE_STATE_DISCONNECTED); + + nm_clear_g_cancellable(&info->cancellable); + info->cancellable = g_cancellable_new(); + success = NM_DEVICE_GET_CLASS(self)->attach_port(self, + slave, + connection, + configure, + info->cancellable, + attach_port_cb, + slave); + + if (success == NM_TERNARY_DEFAULT) + return; + } + + attach_port_done(self, slave, success); } /** @@ -5986,7 +6196,7 @@ nm_device_master_release_slave(NMDevice *self, RELEASE_SLAVE_TYPE_NO_CONFIG, RELEASE_SLAVE_TYPE_CONFIG, RELEASE_SLAVE_TYPE_CONFIG_FORCE)); - g_return_if_fail(NM_DEVICE_GET_CLASS(self)->release_slave != NULL); + g_return_if_fail(NM_DEVICE_GET_CLASS(self)->detach_port != NULL); info = find_slave_info(self, slave); @@ -6007,13 +6217,14 @@ nm_device_master_release_slave(NMDevice *self, g_return_if_fail(self == slave_priv->master); nm_assert(slave == info->slave); + nm_clear_g_cancellable(&info->cancellable); /* first, let subclasses handle the release ... */ if (info->slave_is_enslaved || nm_device_sys_iface_state_is_external(slave) || release_type >= RELEASE_SLAVE_TYPE_CONFIG_FORCE) - NM_DEVICE_GET_CLASS(self)->release_slave(self, - slave, - release_type >= RELEASE_SLAVE_TYPE_CONFIG); + NM_DEVICE_GET_CLASS(self)->detach_port(self, + slave, + release_type >= RELEASE_SLAVE_TYPE_CONFIG); /* raise notifications about the release, including clearing is_enslaved. */ nm_device_slave_notify_release(slave, reason); @@ -6344,7 +6555,7 @@ device_recheck_slave_status(NMDevice *self, const NMPlatformLink *plink) NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED); } - if (master && NM_DEVICE_GET_CLASS(master)->enslave_slave) { + if (master && NM_DEVICE_GET_CLASS(master)->attach_port) { nm_device_master_add_slave(master, self, FALSE); goto out; } @@ -7540,8 +7751,9 @@ slave_state_changed(NMDevice *slave, } if (release) { - configure = priv->sys_iface_state == NM_DEVICE_SYS_IFACE_STATE_MANAGED - && nm_device_sys_iface_state_get(slave) != NM_DEVICE_SYS_IFACE_STATE_EXTERNAL; + configure = (priv->sys_iface_state == NM_DEVICE_SYS_IFACE_STATE_MANAGED + && nm_device_sys_iface_state_get(slave) != NM_DEVICE_SYS_IFACE_STATE_EXTERNAL) + || nm_device_sys_iface_state_get(slave) == NM_DEVICE_SYS_IFACE_STATE_MANAGED; nm_device_master_release_slave(self, slave, @@ -7577,7 +7789,7 @@ nm_device_master_add_slave(NMDevice *self, NMDevice *slave, gboolean configure) g_return_val_if_fail(NM_IS_DEVICE(self), FALSE); g_return_val_if_fail(NM_IS_DEVICE(slave), FALSE); - g_return_val_if_fail(NM_DEVICE_GET_CLASS(self)->enslave_slave != NULL, FALSE); + g_return_val_if_fail(NM_DEVICE_GET_CLASS(self)->attach_port, FALSE); priv = NM_DEVICE_GET_PRIVATE(self); slave_priv = NM_DEVICE_GET_PRIVATE(slave); @@ -7806,6 +8018,9 @@ nm_device_slave_notify_release(NMDevice *self, NMDeviceStateReason reason) g_return_if_fail(priv->master); + if (!priv->is_enslaved) + return; + if (priv->state > NM_DEVICE_STATE_DISCONNECTED && priv->state <= NM_DEVICE_STATE_ACTIVATED) { switch (nm_device_state_reason_check(reason)) { case NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED: @@ -7835,14 +8050,12 @@ nm_device_slave_notify_release(NMDevice *self, NMDeviceStateReason reason) } else _LOGI(LOGD_DEVICE, "released from master device %s", nm_device_get_iface(priv->master)); - if (priv->is_enslaved) { - priv->is_enslaved = FALSE; + priv->is_enslaved = FALSE; - _notify(self, PROP_MASTER); + _notify(self, PROP_MASTER); - nm_clear_pointer(&NM_DEVICE_GET_PRIVATE(priv->master)->ports_variant, g_variant_unref); - nm_gobject_notify_together(priv->master, PROP_PORTS, PROP_SLAVES); - } + nm_clear_pointer(&NM_DEVICE_GET_PRIVATE(priv->master)->ports_variant, g_variant_unref); + nm_gobject_notify_together(priv->master, PROP_PORTS, PROP_SLAVES); } /** @@ -8161,13 +8374,13 @@ device_has_config(NMDevice *self) head_entry = nm_platform_lookup( nm_device_get_platform(self), - nmp_lookup_init_object(&lookup, NMP_OBJECT_TYPE_IP4_ADDRESS, pllink->ifindex)); + nmp_lookup_init_object_by_ifindex(&lookup, NMP_OBJECT_TYPE_IP4_ADDRESS, pllink->ifindex)); if (head_entry) return TRUE; head_entry = nm_platform_lookup( nm_device_get_platform(self), - nmp_lookup_init_object(&lookup, NMP_OBJECT_TYPE_IP6_ADDRESS, pllink->ifindex)); + nmp_lookup_init_object_by_ifindex(&lookup, NMP_OBJECT_TYPE_IP6_ADDRESS, pllink->ifindex)); if (head_entry) return TRUE; @@ -9329,13 +9542,13 @@ lldp_setup(NMDevice *self, NMTernary enabled) static void _routing_rules_sync(NMDevice *self, NMTernary set_mode) { - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - NMPRouteManager *route_manager = nm_netns_get_route_manager(nm_device_get_netns(self)); - NMDeviceClass *klass = NM_DEVICE_GET_CLASS(self); - gboolean untrack_only_dirty = FALSE; - gboolean keep_deleted_rules; - gpointer user_tag_1; - gpointer user_tag_2; + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + NMPGlobalTracker *global_tracker = nm_netns_get_global_tracker(nm_device_get_netns(self)); + NMDeviceClass *klass = NM_DEVICE_GET_CLASS(self); + gboolean untrack_only_dirty = FALSE; + gboolean keep_deleted_rules; + gpointer user_tag_1; + gpointer user_tag_2; /* take two arbitrary user-tag pointers that belong to @self. */ user_tag_1 = &priv->v4_route_table; @@ -9367,13 +9580,13 @@ _routing_rules_sync(NMDevice *self, NMTernary set_mode) nm_ip_routing_rule_to_platform(rule, &plrule); /* We track this rule, but we also make it explicitly not weakly-tracked - * (meaning to untrack NMP_ROUTE_MANAGER_EXTERN_WEAKLY_TRACKED_USER_TAG at + * (meaning to untrack NMP_GLOBAL_TRACKER_EXTERN_WEAKLY_TRACKED_USER_TAG at * the same time). */ - nmp_route_manager_track_rule(route_manager, - &plrule, - 10, - user_tag_1, - NMP_ROUTE_MANAGER_EXTERN_WEAKLY_TRACKED_USER_TAG); + nmp_global_tracker_track_rule(global_tracker, + &plrule, + 10, + user_tag_1, + NMP_GLOBAL_TRACKER_EXTERN_WEAKLY_TRACKED_USER_TAG); } } @@ -9383,25 +9596,25 @@ _routing_rules_sync(NMDevice *self, NMTernary set_mode) extra_rules = klass->get_extra_rules(self); if (extra_rules) { for (i = 0; i < extra_rules->len; i++) { - nmp_route_manager_track_rule( - route_manager, + nmp_global_tracker_track_rule( + global_tracker, NMP_OBJECT_CAST_ROUTING_RULE(extra_rules->pdata[i]), 10, user_tag_2, - NMP_ROUTE_MANAGER_EXTERN_WEAKLY_TRACKED_USER_TAG); + NMP_GLOBAL_TRACKER_EXTERN_WEAKLY_TRACKED_USER_TAG); } } } } - nmp_route_manager_untrack_all(route_manager, user_tag_1, !untrack_only_dirty, TRUE); + nmp_global_tracker_untrack_all(global_tracker, user_tag_1, !untrack_only_dirty, TRUE); if (klass->get_extra_rules) - nmp_route_manager_untrack_all(route_manager, user_tag_2, !untrack_only_dirty, TRUE); + nmp_global_tracker_untrack_all(global_tracker, user_tag_2, !untrack_only_dirty, TRUE); keep_deleted_rules = FALSE; if (set_mode == NM_TERNARY_DEFAULT) { /* when exiting NM, we leave the device up and the rules configured. - * We just call nmp_route_manager_sync() to forget about the synced rules, + * We just call nmp_global_tracker_sync() to forget about the synced rules, * but we don't actually delete them. * * FIXME: that is a problem after restart of NetworkManager, because these @@ -9415,7 +9628,7 @@ _routing_rules_sync(NMDevice *self, NMTernary set_mode) * file and track them after restart again. */ keep_deleted_rules = TRUE; } - nmp_route_manager_sync(route_manager, NMP_OBJECT_TYPE_ROUTING_RULE, keep_deleted_rules); + nmp_global_tracker_sync(global_tracker, NMP_OBJECT_TYPE_ROUTING_RULE, keep_deleted_rules); } static gboolean @@ -10045,6 +10258,7 @@ _dev_ipdhcpx_notify(NMDhcpClient *client, const NMDhcpClientNotifyData *notify_d FALSE); if (notify_data->lease_update.accepted) { + nm_manager_write_device_state(priv->manager, self, NULL); if (priv->ipdhcp_data_x[IS_IPv4].state != NM_DEVICE_IP_STATE_READY) { _dev_ipdhcpx_set_state(self, addr_family, NM_DEVICE_IP_STATE_READY); nm_dispatcher_call_device(NM_DISPATCHER_ACTION_DHCP_CHANGE_X(IS_IPv4), @@ -10190,7 +10404,11 @@ _dev_ipdhcpx_start(NMDevice *self, int addr_family) .vendor_class_identifier = vendor_class_identifier, .use_fqdn = hostname_is_fqdn, .reject_servers = reject_servers, - .v4.request_broadcast = request_broadcast, + .v4 = + { + .request_broadcast = request_broadcast, + .acd_timeout_msec = _prop_get_ipv4_dad_timeout(self), + }, }; priv->ipdhcp_data_4.client = @@ -10205,22 +10423,25 @@ _dev_ipdhcpx_start(NMDevice *self, int addr_family) duid = _prop_get_ipv6_dhcp_duid(self, connection, hwaddr, &enforce_duid); config = (NMDhcpClientConfig){ - .addr_family = AF_INET6, - .l3cfg = nm_device_get_l3cfg(self), - .iface = nm_device_get_ip_iface(self), - .uuid = nm_connection_get_uuid(connection), - .send_hostname = nm_setting_ip_config_get_dhcp_send_hostname(s_ip), - .hostname = nm_setting_ip_config_get_dhcp_hostname(s_ip), - .hostname_flags = _prop_get_ipvx_dhcp_hostname_flags(self, AF_INET6), - .client_id = duid, - .mud_url = _prop_get_connection_mud_url(self, s_con), - .timeout = no_lease_timeout_sec, - .anycast_address = _device_get_dhcp_anycast_address(self), - .v6.enforce_duid = enforce_duid, - .v6.iaid = iaid, - .v6.iaid_explicit = iaid_explicit, - .v6.info_only = (priv->ipdhcp_data_6.v6.mode == NM_NDISC_DHCP_LEVEL_OTHERCONF), - .v6.needed_prefixes = priv->ipdhcp_data_6.v6.needed_prefixes, + .addr_family = AF_INET6, + .l3cfg = nm_device_get_l3cfg(self), + .iface = nm_device_get_ip_iface(self), + .uuid = nm_connection_get_uuid(connection), + .send_hostname = nm_setting_ip_config_get_dhcp_send_hostname(s_ip), + .hostname = nm_setting_ip_config_get_dhcp_hostname(s_ip), + .hostname_flags = _prop_get_ipvx_dhcp_hostname_flags(self, AF_INET6), + .client_id = duid, + .mud_url = _prop_get_connection_mud_url(self, s_con), + .timeout = no_lease_timeout_sec, + .anycast_address = _device_get_dhcp_anycast_address(self), + .v6 = + { + .enforce_duid = enforce_duid, + .iaid = iaid, + .iaid_explicit = iaid_explicit, + .info_only = (priv->ipdhcp_data_6.v6.mode == NM_NDISC_DHCP_LEVEL_OTHERCONF), + .needed_prefixes = priv->ipdhcp_data_6.v6.needed_prefixes, + }, }; priv->ipdhcp_data_6.client = @@ -10635,7 +10856,6 @@ _dev_ipll6_start(NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); NMConnection *connection; - NMSettingIP6Config *s_ip6 = NULL; gboolean assume; const char *ifname; NML3IPv6LLState llstate; @@ -10656,14 +10876,10 @@ _dev_ipll6_start(NMDevice *self) } connection = nm_device_get_applied_connection(self); - if (connection) - s_ip6 = NM_SETTING_IP6_CONFIG(nm_connection_get_setting_ip6_config(connection)); assume = nm_device_sys_iface_state_is_external_or_assume(self); - if (s_ip6 - && nm_setting_ip6_config_get_addr_gen_mode(s_ip6) - == NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY) { + if (_prop_get_ipv6_addr_gen_mode(self) == NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY) { NMUtilsStableType stable_type; const char *stable_id; @@ -10866,9 +11082,10 @@ _commit_mtu(NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); NMDeviceMtuSource source = NM_DEVICE_MTU_SOURCE_NONE; + NMSettingIPConfig *s_ip6; const NML3ConfigData *l3cd; guint32 ip6_mtu_orig; - guint32 ip6_mtu; + guint32 ip6_mtu = 0; guint32 mtu_desired_orig; guint32 mtu_desired; guint32 mtu_plat; @@ -10953,10 +11170,9 @@ _commit_mtu(NMDevice *self) } } - if (mtu_desired && mtu_desired < 1280) { - NMSettingIPConfig *s_ip6; + s_ip6 = nm_device_get_applied_setting(self, NM_TYPE_SETTING_IP6_CONFIG); - s_ip6 = nm_device_get_applied_setting(self, NM_TYPE_SETTING_IP6_CONFIG); + if (mtu_desired && mtu_desired < 1280) { if (s_ip6 && !NM_IN_STRSET(nm_setting_ip_config_get_method(s_ip6), NM_SETTING_IP6_CONFIG_METHOD_IGNORE, @@ -10971,7 +11187,12 @@ _commit_mtu(NMDevice *self) } } - ip6_mtu = priv->ip6_mtu; + if (s_ip6) + ip6_mtu = nm_setting_ip6_config_get_mtu(NM_SETTING_IP6_CONFIG(s_ip6)); + + if (!ip6_mtu) + ip6_mtu = priv->ip6_mtu; + if (!ip6_mtu && priv->mtu_source == NM_DEVICE_MTU_SOURCE_NONE) { /* initially, if the IPv6 MTU is not specified, grow it as large as the * link MTU @mtu_desired. Only exception is, if @mtu_desired is so small @@ -11353,7 +11574,7 @@ _dev_ipac6_start(NMDevice *self) .ifname = nm_device_get_ip_iface(self), .stable_type = stable_type, .network_id = stable_id, - .addr_gen_mode = nm_setting_ip6_config_get_addr_gen_mode(s_ip), + .addr_gen_mode = _prop_get_ipv6_addr_gen_mode(self), .node_type = node_type, .max_addresses = max_addresses, .router_solicitations = router_solicitations, @@ -11640,11 +11861,14 @@ activate_stage3_ip_config_for_addr_family(NMDevice *self, int addr_family, const goto out_devip; if (IS_IPv4) { + if (_prop_get_ipv4_link_local(self) == NM_SETTING_IP4_LL_ENABLED) + _dev_ipll4_start(self); + if (nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) _dev_ipdhcpx_start(self, AF_INET); - else if (nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL)) - _dev_ipll4_start(self); - else if (nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_SHARED)) + else if (nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL)) { + /* pass */ + } else if (nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_SHARED)) _dev_ipshared4_start(self); else if (nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED)) priv->ip_data_x[IS_IPv4].is_disabled = TRUE; @@ -12344,7 +12568,8 @@ delete_on_deactivate_check_and_schedule(NMDevice *self) static void _cleanup_ip_pre(NMDevice *self, int addr_family, CleanupType cleanup_type, gboolean from_reapply) { - const int IS_IPv4 = NM_IS_IPv4(addr_family); + const int IS_IPv4 = NM_IS_IPv4(addr_family); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); _dev_ipsharedx_cleanup(self, addr_family); @@ -12360,6 +12585,9 @@ _cleanup_ip_pre(NMDevice *self, int addr_family, CleanupType cleanup_type, gbool _dev_ipmanual_cleanup(self); + nm_clear_g_signal_handler(nm_manager_get_dns_manager(priv->manager), + &priv->ip_data.dnsmgr_update_pending_signal_id); + _dev_ip_state_cleanup(self, AF_UNSPEC, from_reapply); _dev_ip_state_cleanup(self, addr_family, from_reapply); } @@ -12479,12 +12707,15 @@ can_reapply_change(NMDevice *self, NM_SETTING_CONNECTION_STABLE_ID, NM_SETTING_CONNECTION_AUTOCONNECT, NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES, + NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY, NM_SETTING_CONNECTION_ZONE, NM_SETTING_CONNECTION_METERED, NM_SETTING_CONNECTION_LLDP, NM_SETTING_CONNECTION_MDNS, NM_SETTING_CONNECTION_LLMNR, - NM_SETTING_CONNECTION_DNS_OVER_TLS); + NM_SETTING_CONNECTION_DNS_OVER_TLS, + NM_SETTING_CONNECTION_MPTCP_FLAGS, + NM_SETTING_CONNECTION_WAIT_ACTIVATION_DELAY); } if (NM_IN_STRSET(setting_name, @@ -12700,7 +12931,8 @@ check_and_reapply_connection(NMDevice *self, NM_SETTING_CONNECTION_LLDP, NM_SETTING_CONNECTION_MDNS, NM_SETTING_CONNECTION_LLMNR, - NM_SETTING_CONNECTION_DNS_OVER_TLS)) { + NM_SETTING_CONNECTION_DNS_OVER_TLS, + NM_SETTING_CONNECTION_MPTCP_FLAGS)) { priv->ip_data_4.do_reapply = TRUE; priv->ip_data_6.do_reapply = TRUE; } @@ -13361,29 +13593,71 @@ _dispatcher_cleanup(NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + nm_clear_g_source_inst(&priv->delay_activation_source); + if (!priv->dispatcher.call_id) return FALSE; nm_dispatcher_call_cancel(g_steal_pointer(&priv->dispatcher.call_id)); priv->dispatcher.post_state = NM_DEVICE_STATE_UNKNOWN; priv->dispatcher.post_state_reason = NM_DEVICE_STATE_REASON_NONE; + return TRUE; } static void -_dispatcher_complete_proceed_state(NMDispatcherCallId *call_id, gpointer user_data) +_queue_dispatcher_post_state(NMDevice *self) { - NMDevice *self = NM_DEVICE(user_data); NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - g_return_if_fail(call_id == priv->dispatcher.call_id); - - priv->dispatcher.call_id = NULL; nm_device_queue_state(self, priv->dispatcher.post_state, priv->dispatcher.post_state_reason); priv->dispatcher.post_state = NM_DEVICE_STATE_UNKNOWN; priv->dispatcher.post_state_reason = NM_DEVICE_STATE_REASON_NONE; } +static gboolean +_wait_activation_delay_timeout(gpointer user_data) +{ + NMDevice *self = user_data; + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + + nm_clear_g_source_inst(&priv->delay_activation_source); + + _LOGD(LOGD_DEVICE, "finished waiting on activation delay"); + _queue_dispatcher_post_state(self); + + return G_SOURCE_REMOVE; +} + +static void +_dispatcher_complete_proceed_state(NMDispatcherCallId *call_id, gpointer user_data) +{ + NMDevice *self = NM_DEVICE(user_data); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + NMConnection *conn; + NMSettingConnection *s_conn; + gint32 delay_timeout; + + g_return_if_fail(call_id == priv->dispatcher.call_id); + nm_assert(!priv->delay_activation_source); + + priv->dispatcher.call_id = NULL; + conn = nm_device_get_applied_connection(self); + if (conn) { + s_conn = nm_connection_get_setting_connection(conn); + if (s_conn) { + delay_timeout = nm_setting_connection_get_wait_activation_delay(s_conn); + if (delay_timeout > 0) { + priv->delay_activation_source = + nm_g_timeout_add_source(delay_timeout, _wait_activation_delay_timeout, self); + return; + } + } + } + + _queue_dispatcher_post_state(self); +} + /*****************************************************************************/ static void @@ -13437,14 +13711,14 @@ spawn_ping(NMDevice *self) gs_free char *str_timeout = NULL; gs_free char *tmp_str = NULL; const char *args[] = {priv->gw_ping.binary, - "-I", - nm_device_get_ip_iface(self), - "-c", - "1", - "-w", - NULL, - priv->gw_ping.address, - NULL}; + "-I", + nm_device_get_ip_iface(self), + "-c", + "1", + "-w", + NULL, + priv->gw_ping.address, + NULL}; gs_free_error GError *error = NULL; gboolean ret; @@ -13665,10 +13939,38 @@ _get_carrier_wait_ms(NMDevice *self) CARRIER_WAIT_TIME_MS); } +/* + * Devices that support carrier detect must be IFF_UP to report carrier + * changes; so after setting the device IFF_UP we must suppress startup + * complete (via a pending action) until either the carrier turns on, or + * a timeout is reached. + */ +static void +carrier_detect_wait(NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + gint64 now_ms, until_ms; + + if (!nm_device_has_capability(self, NM_DEVICE_CAP_CARRIER_DETECT)) + return; + + /* we start a grace period of 5 seconds during which we will schedule + * a pending action whenever we have no carrier. + * + * If during that time carrier goes away, we declare the interface + * as not ready. */ + nm_clear_g_source(&priv->carrier_wait_id); + if (!priv->carrier) + nm_device_add_pending_action(self, NM_PENDING_ACTION_CARRIER_WAIT, FALSE); + + now_ms = nm_utils_get_monotonic_timestamp_msec(); + until_ms = NM_MAX(now_ms + _get_carrier_wait_ms(self), priv->carrier_wait_until_ms); + priv->carrier_wait_id = g_timeout_add(until_ms - now_ms, carrier_wait_timeout, self); +} + gboolean nm_device_bring_up(NMDevice *self, gboolean block, gboolean *no_firmware) { - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); gboolean device_is_up = FALSE; NMDeviceCapabilities capabilities; int ifindex; @@ -13724,27 +14026,7 @@ nm_device_bring_up(NMDevice *self, gboolean block, gboolean *no_firmware) capabilities |= NM_DEVICE_GET_CLASS(self)->get_generic_capabilities(self); _add_capabilities(self, capabilities); - /* Devices that support carrier detect must be IFF_UP to report carrier - * changes; so after setting the device IFF_UP we must suppress startup - * complete (via a pending action) until either the carrier turns on, or - * a timeout is reached. - */ - if (nm_device_has_capability(self, NM_DEVICE_CAP_CARRIER_DETECT)) { - gint64 now_ms, until_ms; - - /* we start a grace period of 5 seconds during which we will schedule - * a pending action whenever we have no carrier. - * - * If during that time carrier goes away, we declare the interface - * as not ready. */ - nm_clear_g_source(&priv->carrier_wait_id); - if (!priv->carrier) - nm_device_add_pending_action(self, NM_PENDING_ACTION_CARRIER_WAIT, FALSE); - - now_ms = nm_utils_get_monotonic_timestamp_msec(); - until_ms = NM_MAX(now_ms + _get_carrier_wait_ms(self), priv->carrier_wait_until_ms); - priv->carrier_wait_id = g_timeout_add(until_ms - now_ms, carrier_wait_timeout, self); - } + carrier_detect_wait(self); /* Can only get HW address of some devices when they are up */ nm_device_update_hw_address(self); @@ -14997,6 +15279,9 @@ _cancel_activation(NMDevice *self) _dispatcher_cleanup(self); ip_check_gw_ping_cleanup(self); + _dev_ip_state_cleanup(self, AF_INET, FALSE); + _dev_ip_state_cleanup(self, AF_INET6, FALSE); + /* Break the activation chain */ activation_source_clear(self); } @@ -15500,6 +15785,13 @@ _set_state_full(NMDevice *self, NMDeviceState state, NMDeviceStateReason reason, if (!nm_device_bring_up(self, TRUE, &no_firmware) && no_firmware) _LOGW(LOGD_PLATFORM, "firmware may be missing."); nm_device_set_firmware_missing(self, no_firmware ? TRUE : FALSE); + } else { + /* We didn't bring the device up and we have little idea + * when was it brought up. Play it safe and assume it could + * have been brought up very recently and it might one of + * those who take time to detect carrier. + */ + carrier_detect_wait(self); } /* Ensure the device gets deactivated in response to stuff like @@ -16804,7 +17096,7 @@ get_address_for_hostname_dns_lookup(NMDevice *self, int addr_family) * opposed to an address that is configured? */ head_entry = nm_platform_lookup( nm_device_get_platform(self), - nmp_lookup_init_object(&lookup, NMP_OBJECT_TYPE_IP_ADDRESS(IS_IPv4), ifindex)); + nmp_lookup_init_object_by_ifindex(&lookup, NMP_OBJECT_TYPE_IP_ADDRESS(IS_IPv4), ifindex)); if (head_entry) { c_list_for_each_entry (iter, &head_entry->lst_entries_head, lst_entries) { diff --git a/src/core/devices/nm-device.h b/src/core/devices/nm-device.h index d59aecb2..382c8660 100644 --- a/src/core/devices/nm-device.h +++ b/src/core/devices/nm-device.h @@ -163,6 +163,7 @@ typedef enum { } NMDeviceCheckDevAvailableFlags; typedef void (*NMDeviceDeactivateCallback)(NMDevice *self, GError *error, gpointer user_data); +typedef void (*NMDeviceAttachPortCallback)(NMDevice *self, GError *error, gpointer user_data); typedef struct _NMDeviceClass { NMDBusObjectClass parent; @@ -373,12 +374,18 @@ typedef struct _NMDeviceClass { NMConnection *connection, GError **error); - gboolean (*enslave_slave)(NMDevice *self, - NMDevice *slave, - NMConnection *connection, - gboolean configure); - - void (*release_slave)(NMDevice *self, NMDevice *slave, gboolean configure); + /* Attachs a port asynchronously. Returns TRUE/FALSE on immediate + * success/error; in such cases, the callback is not invoked. If the + * action couldn't be completed immediately, DEFAULT is returned and + * the callback will always be invoked asynchronously. */ + NMTernary (*attach_port)(NMDevice *self, + NMDevice *port, + NMConnection *connection, + gboolean configure, + GCancellable *cancellable, + NMDeviceAttachPortCallback callback, + gpointer user_data); + void (*detach_port)(NMDevice *self, NMDevice *port, gboolean configure); void (*parent_changed_notify)(NMDevice *self, int old_ifindex, diff --git a/src/core/devices/ovs/nm-device-ovs-bridge.c b/src/core/devices/ovs/nm-device-ovs-bridge.c index ea77dd18..048afb02 100644 --- a/src/core/devices/ovs/nm-device-ovs-bridge.c +++ b/src/core/devices/ovs/nm-device-ovs-bridge.c @@ -78,20 +78,26 @@ act_stage3_ip_config(NMDevice *device, int addr_family) nm_device_devip_set_state(device, addr_family, NM_DEVICE_IP_STATE_READY, NULL); } -static gboolean -enslave_slave(NMDevice *device, NMDevice *slave, NMConnection *connection, gboolean configure) +static NMTernary +attach_port(NMDevice *device, + NMDevice *port, + NMConnection *connection, + gboolean configure, + GCancellable *cancellable, + NMDeviceAttachPortCallback callback, + gpointer user_data) { if (!configure) return TRUE; - if (!NM_IS_DEVICE_OVS_PORT(slave)) + if (!NM_IS_DEVICE_OVS_PORT(port)) return FALSE; return TRUE; } static void -release_slave(NMDevice *device, NMDevice *slave, gboolean configure) +detach_port(NMDevice *device, NMDevice *port, gboolean configure) {} void @@ -159,8 +165,8 @@ nm_device_ovs_bridge_class_init(NMDeviceOvsBridgeClass *klass) 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->enslave_slave = enslave_slave; - device_class->release_slave = release_slave; + device_class->attach_port = attach_port; + device_class->detach_port = detach_port; device_class->can_reapply_change_ovs_external_ids = TRUE; 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 6ba52f40..5510e39f 100644 --- a/src/core/devices/ovs/nm-device-ovs-port.c +++ b/src/core/devices/ovs/nm-device-ovs-port.c @@ -72,20 +72,42 @@ act_stage3_ip_config(NMDevice *device, int addr_family) nm_device_devip_set_state(device, addr_family, NM_DEVICE_IP_STATE_READY, NULL); } +typedef struct { + NMDevice *device; + NMDevice *port; + GCancellable *cancellable; + NMDeviceAttachPortCallback callback; + gpointer callback_user_data; +} AttachPortData; + static void add_iface_cb(GError *error, gpointer user_data) { - NMDevice *slave = user_data; - - if (error && !g_error_matches(error, NM_UTILS_ERROR, NM_UTILS_ERROR_CANCELLED_DISPOSING)) { - nm_log_warn(LOGD_DEVICE, - "device %s could not be added to a ovs port: %s", - nm_device_get_iface(slave), - error->message); - nm_device_state_changed(slave, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_OVSDB_FAILED); + AttachPortData *data = user_data; + NMDeviceOvsPort *self; + gs_free_error GError *local = NULL; + + if (g_cancellable_is_cancelled(data->cancellable)) { + local = nm_utils_error_new_cancelled(FALSE, NULL); + error = local; + } else if (error && !nm_utils_error_is_cancelled_or_disposing(error)) { + self = NM_DEVICE_OVS_PORT(data->device); + _LOGW(LOGD_DEVICE, + "device %s could not be added to a ovs port: %s", + nm_device_get_iface(data->port), + error->message); + nm_device_state_changed(data->port, + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_OVSDB_FAILED); } - g_object_unref(slave); + data->callback(data->device, error, data->callback_user_data); + + g_object_unref(data->device); + g_object_unref(data->port); + nm_clear_g_cancellable(&data->cancellable); + + nm_g_slice_free(data); } static gboolean @@ -115,14 +137,21 @@ set_mtu_cb(GError *error, gpointer user_data) g_object_unref(self); } -static gboolean -enslave_slave(NMDevice *device, NMDevice *slave, NMConnection *connection, gboolean configure) +static NMTernary +attach_port(NMDevice *device, + NMDevice *port, + NMConnection *connection, + gboolean configure, + GCancellable *cancellable, + NMDeviceAttachPortCallback callback, + gpointer user_data) { NMDeviceOvsPort *self = NM_DEVICE_OVS_PORT(device); NMActiveConnection *ac_port = NULL; NMActiveConnection *ac_bridge = NULL; NMDevice *bridge_device; NMSettingWired *s_wired; + AttachPortData *data; if (!configure) return TRUE; @@ -131,42 +160,49 @@ enslave_slave(NMDevice *device, NMDevice *slave, NMConnection *connection, gbool ac_bridge = nm_active_connection_get_master(ac_port); if (!ac_bridge) { _LOGW(LOGD_DEVICE, - "can't enslave %s: bridge active-connection not found", - nm_device_get_iface(slave)); + "can't attach %s: bridge active-connection not found", + nm_device_get_iface(port)); return FALSE; } bridge_device = nm_active_connection_get_device(ac_bridge); if (!bridge_device) { - _LOGW(LOGD_DEVICE, "can't enslave %s: bridge device not found", nm_device_get_iface(slave)); + _LOGW(LOGD_DEVICE, "can't attach %s: bridge device not found", nm_device_get_iface(port)); return FALSE; } + data = g_slice_new(AttachPortData); + *data = (AttachPortData){ + .device = g_object_ref(device), + .port = g_object_ref(port), + .cancellable = g_object_ref(cancellable), + .callback = callback, + .callback_user_data = user_data, + }; + nm_ovsdb_add_interface(nm_ovsdb_get(), nm_active_connection_get_applied_connection(ac_bridge), nm_device_get_applied_connection(device), - nm_device_get_applied_connection(slave), + nm_device_get_applied_connection(port), bridge_device, - slave, + port, add_iface_cb, - g_object_ref(slave)); + data); /* DPDK ports does not have a link after the devbind, so the MTU must be * set on ovsdb after adding the interface. */ - if (NM_IS_DEVICE_OVS_INTERFACE(slave) && _ovs_interface_is_dpdk(slave)) { - s_wired = nm_device_get_applied_setting(slave, NM_TYPE_SETTING_WIRED); - - if (!s_wired || !nm_setting_wired_get_mtu(s_wired)) - return TRUE; - - nm_ovsdb_set_interface_mtu(nm_ovsdb_get(), - nm_device_get_ip_iface(slave), - nm_setting_wired_get_mtu(s_wired), - set_mtu_cb, - g_object_ref(slave)); + if (NM_IS_DEVICE_OVS_INTERFACE(port) && _ovs_interface_is_dpdk(port)) { + s_wired = nm_device_get_applied_setting(port, NM_TYPE_SETTING_WIRED); + if (s_wired && nm_setting_wired_get_mtu(s_wired)) { + nm_ovsdb_set_interface_mtu(nm_ovsdb_get(), + nm_device_get_ip_iface(port), + nm_setting_wired_get_mtu(s_wired), + set_mtu_cb, + g_object_ref(port)); + } } - return TRUE; + return NM_TERNARY_DEFAULT; } static void @@ -186,31 +222,31 @@ del_iface_cb(GError *error, gpointer user_data) } static void -release_slave(NMDevice *device, NMDevice *slave, gboolean configure) +detach_port(NMDevice *device, NMDevice *port, gboolean configure) { - NMDeviceOvsPort *self = NM_DEVICE_OVS_PORT(device); - bool slave_not_managed = !NM_IN_SET(nm_device_sys_iface_state_get(slave), - NM_DEVICE_SYS_IFACE_STATE_MANAGED, - NM_DEVICE_SYS_IFACE_STATE_ASSUME); + NMDeviceOvsPort *self = NM_DEVICE_OVS_PORT(device); + bool port_not_managed = !NM_IN_SET(nm_device_sys_iface_state_get(port), + NM_DEVICE_SYS_IFACE_STATE_MANAGED, + NM_DEVICE_SYS_IFACE_STATE_ASSUME); - _LOGI(LOGD_DEVICE, "releasing ovs interface %s", nm_device_get_ip_iface(slave)); + _LOGI(LOGD_DEVICE, "detaching ovs interface %s", nm_device_get_ip_iface(port)); /* Even if the an interface's device has gone away (e.g. externally * removed and thus we're called with configure=FALSE), we still need * to make sure its OVSDB entry is gone. */ - if (configure || slave_not_managed) { + if (configure || port_not_managed) { nm_ovsdb_del_interface(nm_ovsdb_get(), - nm_device_get_iface(slave), + nm_device_get_iface(port), del_iface_cb, - g_object_ref(slave)); + g_object_ref(port)); } if (configure) { /* Open VSwitch is going to delete this one. We must ignore what happens * next with the interface. */ - if (NM_IS_DEVICE_OVS_INTERFACE(slave)) - nm_device_update_from_platform_link(slave, NULL); + if (NM_IS_DEVICE_OVS_INTERFACE(port)) + nm_device_update_from_platform_link(port, NULL); } } @@ -245,8 +281,8 @@ nm_device_ovs_port_class_init(NMDeviceOvsPortClass *klass) 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->enslave_slave = enslave_slave; - device_class->release_slave = release_slave; + device_class->attach_port = attach_port; + device_class->detach_port = detach_port; device_class->can_reapply_change_ovs_external_ids = TRUE; 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 5aaa5c01..ff2c7858 100644 --- a/src/core/devices/ovs/nm-ovs-factory.c +++ b/src/core/devices/ovs/nm-ovs-factory.c @@ -178,7 +178,8 @@ ovsdb_device_removed(NMOvsdb *ovsdb, device_state = nm_device_get_state(device); if (device_type == NM_DEVICE_TYPE_OVS_INTERFACE && nm_device_get_act_request(device) - && device_state < NM_DEVICE_STATE_DEACTIVATING) { + && (device_state > NM_DEVICE_STATE_DISCONNECTED + && device_state < NM_DEVICE_STATE_DEACTIVATING)) { nm_device_state_changed(device, NM_DEVICE_STATE_DEACTIVATING, NM_DEVICE_STATE_REASON_REMOVED); diff --git a/src/core/devices/ovs/nm-ovsdb.c b/src/core/devices/ovs/nm-ovsdb.c index 44e16cb7..e7c96852 100644 --- a/src/core/devices/ovs/nm-ovsdb.c +++ b/src/core/devices/ovs/nm-ovsdb.c @@ -376,6 +376,9 @@ ovsdb_call_method(NMOvsdb *self, NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE(self); OvsdbMethodCall *call; + /* FIXME(shutdown): this function should accept a cancellable to + * interrupt the operation. */ + /* Ensure we're not unsynchronized before we queue the method call. */ ovsdb_try_connect(self); @@ -1550,7 +1553,7 @@ _external_ids_to_string(const GArray *arr) if (!arr) return g_strdup("empty"); - nm_str_buf_init(&strbuf, NM_UTILS_GET_NEXT_REALLOC_SIZE_104, FALSE); + strbuf = NM_STR_BUF_INIT(NM_UTILS_GET_NEXT_REALLOC_SIZE_104, FALSE); nm_str_buf_append(&strbuf, "["); for (i = 0; i < arr->len; i++) { const NMUtilsNamedValue *n = &g_array_index(arr, NMUtilsNamedValue, i); @@ -1584,7 +1587,7 @@ ovsdb_got_update(NMOvsdb *self, json_t *msg) json_t *items; json_t *external_ids; json_error_t json_error = { - 0, + 0, }; void *iter; const char *name; @@ -1985,7 +1988,7 @@ ovsdb_got_msg(NMOvsdb *self, json_t *msg) { NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE(self); json_error_t json_error = { - 0, + 0, }; json_t *json_id = NULL; json_int_t id = (json_int_t) -1; @@ -2127,7 +2130,7 @@ ovsdb_read_cb(GObject *source_object, GAsyncResult *res, gpointer user_data) gssize size; json_t *msg; json_error_t json_error = { - 0, + 0, }; size = g_input_stream_read_finish(stream, res, &error); diff --git a/src/core/devices/team/nm-device-team.c b/src/core/devices/team/nm-device-team.c index b67c7100..e6d34266 100644 --- a/src/core/devices/team/nm-device-team.c +++ b/src/core/devices/team/nm-device-team.c @@ -65,6 +65,50 @@ static gboolean teamd_start(NMDeviceTeam *self); /*****************************************************************************/ +static struct teamdctl * +_tdc_connect_new(NMDeviceTeam *self, const char *iface, GError **error) +{ + NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE(self); + struct teamdctl *tdc; + const char *cli_type; + int r; + + tdc = teamdctl_alloc(); + if (!tdc) { + nm_utils_error_set(error, NM_UTILS_ERROR_UNKNOWN, "failure to allocate teamdctl structure"); + g_return_val_if_reached(NULL); + } + + if (priv->teamd_dbus_watch) + cli_type = "dbus"; + else if (priv->usock_monitor) + cli_type = "usock"; + else + cli_type = NULL; + +again: + r = teamdctl_connect(tdc, iface, NULL, cli_type); + if (r != 0) { + _LOGD(LOGD_TEAM, + "failure to connect to teamdctl%s%s, err=%d", + NM_PRINT_FMT_QUOTED2(cli_type, " with cli_type=", cli_type, ""), + r); + if (cli_type) { + /* How odd. Let's retry with any CLI type. */ + cli_type = NULL; + goto again; + } + teamdctl_free(tdc); + nm_utils_error_set(error, + NM_UTILS_ERROR_UNKNOWN, + "failure to connect to teamd (err=%d)", + r); + return NULL; + } + + return tdc; +} + static NMDeviceCapabilities get_generic_capabilities(NMDevice *device) { @@ -96,21 +140,16 @@ complete_connection(NMDevice *device, static gboolean ensure_teamd_connection(NMDevice *device) { - NMDeviceTeam *self = NM_DEVICE_TEAM(device); - NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE(self); - int err; + NMDeviceTeam *self = NM_DEVICE_TEAM(device); + NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE(self); + gs_free_error GError *error = NULL; if (priv->tdc) return TRUE; - priv->tdc = teamdctl_alloc(); - g_assert(priv->tdc); - err = teamdctl_connect(priv->tdc, nm_device_get_iface(device), NULL, NULL); - if (err != 0) { - _LOGE(LOGD_TEAM, "failed to connect to teamd (err=%d)", err); - teamdctl_free(priv->tdc); - priv->tdc = NULL; - } + priv->tdc = _tdc_connect_new(self, nm_device_get_iface(device), &error); + if (!priv->tdc) + _LOGE(LOGD_TEAM, "failed to connect to teamd: %s", error->message); return !!priv->tdc; } @@ -183,42 +222,31 @@ update_connection(NMDevice *device, NMConnection *connection) /*****************************************************************************/ static gboolean -master_update_slave_connection(NMDevice *self, +master_update_slave_connection(NMDevice *device, NMDevice *slave, NMConnection *connection, GError **error) { - NMSettingTeamPort *s_port; - char *port_config = NULL; - int err = 0; - struct teamdctl *tdc; - const char *team_port_config = NULL; - const char *iface = nm_device_get_iface(self); - const char *iface_slave = nm_device_get_iface(slave); - - tdc = teamdctl_alloc(); + NMDeviceTeam *self = NM_DEVICE_TEAM(device); + NMSettingTeamPort *s_port; + char *port_config = NULL; + gs_free_error GError *connect_error = NULL; + int err = 0; + struct teamdctl *tdc; + const char *team_port_config = NULL; + const char *iface = nm_device_get_iface(device); + const char *iface_slave = nm_device_get_iface(slave); + + tdc = _tdc_connect_new(self, iface, &connect_error); if (!tdc) { g_set_error(error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, "update slave connection for slave '%s' failed to connect to teamd for master " - "%s (out of memory?)", - iface_slave, - iface); - g_return_val_if_reached(FALSE); - } - - err = teamdctl_connect(tdc, iface, NULL, NULL); - if (err) { - teamdctl_free(tdc); - g_set_error(error, - NM_DEVICE_ERROR, - NM_DEVICE_ERROR_FAILED, - "update slave connection for slave '%s' failed to connect to teamd for master " - "%s (err=%d)", + "%s (%s)", iface_slave, iface, - err); + connect_error->message); return FALSE; } @@ -790,19 +818,25 @@ deactivate(NMDevice *device) teamd_cleanup(self, TRUE); } -static gboolean -enslave_slave(NMDevice *device, NMDevice *slave, NMConnection *connection, gboolean configure) +static NMTernary +attach_port(NMDevice *device, + NMDevice *port, + NMConnection *connection, + gboolean configure, + GCancellable *cancellable, + NMDeviceAttachPortCallback callback, + gpointer user_data) { - NMDeviceTeam *self = NM_DEVICE_TEAM(device); - NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE(self); - gboolean success = TRUE; - const char *slave_iface = nm_device_get_ip_iface(slave); + NMDeviceTeam *self = NM_DEVICE_TEAM(device); + NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE(self); + gboolean success = TRUE; + const char *port_iface = nm_device_get_ip_iface(port); NMSettingTeamPort *s_team_port; - nm_device_master_check_slave_physical_port(device, slave, LOGD_TEAM); + nm_device_master_check_slave_physical_port(device, port, LOGD_TEAM); if (configure) { - nm_device_take_down(slave, TRUE); + nm_device_take_down(port, TRUE); s_team_port = nm_connection_get_setting_team_port(connection); if (s_team_port) { @@ -811,19 +845,19 @@ enslave_slave(NMDevice *device, NMDevice *slave, NMConnection *connection, gbool if (config) { if (!priv->tdc) { _LOGW(LOGD_TEAM, - "enslaved team port %s config not changed, not connected to teamd", - slave_iface); + "attached team port %s config not changed, not connected to teamd", + port_iface); } else { gs_free char *sanitized_config = NULL; int err; sanitized_config = g_strdup(config); g_strdelimit(sanitized_config, "\r\n", ' '); - err = teamdctl_port_config_update_raw(priv->tdc, slave_iface, sanitized_config); + err = teamdctl_port_config_update_raw(priv->tdc, port_iface, sanitized_config); if (err != 0) { _LOGE(LOGD_TEAM, "failed to update config for port %s (err=%d)", - slave_iface, + port_iface, err); return FALSE; } @@ -832,8 +866,8 @@ enslave_slave(NMDevice *device, NMDevice *slave, NMConnection *connection, gbool } success = nm_platform_link_enslave(nm_device_get_platform(device), nm_device_get_ip_ifindex(device), - nm_device_get_ip_ifindex(slave)); - nm_device_bring_up(slave, TRUE, NULL); + nm_device_get_ip_ifindex(port)); + nm_device_bring_up(port, TRUE, NULL); if (!success) return FALSE; @@ -841,21 +875,21 @@ enslave_slave(NMDevice *device, NMDevice *slave, NMConnection *connection, gbool nm_clear_g_source(&priv->teamd_read_timeout); priv->teamd_read_timeout = g_timeout_add_seconds(5, teamd_read_timeout_cb, self); - _LOGI(LOGD_TEAM, "enslaved team port %s", slave_iface); + _LOGI(LOGD_TEAM, "attached team port %s", port_iface); } else - _LOGI(LOGD_TEAM, "team port %s was enslaved", slave_iface); + _LOGI(LOGD_TEAM, "team port %s was attached", port_iface); return TRUE; } static void -release_slave(NMDevice *device, NMDevice *slave, gboolean configure) +detach_port(NMDevice *device, NMDevice *port, gboolean configure) { NMDeviceTeam *self = NM_DEVICE_TEAM(device); NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE(self); gboolean do_release, success; NMSettingTeamPort *s_port; - int ifindex_slave; + int ifindex_port; int ifindex; do_release = configure; @@ -865,39 +899,39 @@ release_slave(NMDevice *device, NMDevice *slave, gboolean configure) do_release = FALSE; } - ifindex_slave = nm_device_get_ip_ifindex(slave); + ifindex_port = nm_device_get_ip_ifindex(port); - if (ifindex_slave <= 0) { - _LOGD(LOGD_TEAM, "team port %s is already released", nm_device_get_ip_iface(slave)); + if (ifindex_port <= 0) { + _LOGD(LOGD_TEAM, "team port %s is already detached", nm_device_get_ip_iface(port)); } else if (do_release) { success = nm_platform_link_release(nm_device_get_platform(device), nm_device_get_ip_ifindex(device), - ifindex_slave); + ifindex_port); if (success) - _LOGI(LOGD_TEAM, "released team port %s", nm_device_get_ip_iface(slave)); + _LOGI(LOGD_TEAM, "detached team port %s", nm_device_get_ip_iface(port)); else - _LOGW(LOGD_TEAM, "failed to release team port %s", nm_device_get_ip_iface(slave)); + _LOGW(LOGD_TEAM, "failed to detach team port %s", nm_device_get_ip_iface(port)); /* Kernel team code "closes" the port when releasing it, (which clears * IFF_UP), so we must bring it back up here to ensure carrier changes and * other state is noticed by the now-released port. */ - if (!nm_device_bring_up(slave, TRUE, NULL)) { + if (!nm_device_bring_up(port, TRUE, NULL)) { _LOGW(LOGD_TEAM, - "released team port %s could not be brought up", - nm_device_get_ip_iface(slave)); + "detached team port %s could not be brought up", + nm_device_get_ip_iface(port)); } nm_clear_g_source(&priv->teamd_read_timeout); priv->teamd_read_timeout = g_timeout_add_seconds(5, teamd_read_timeout_cb, self); } else - _LOGI(LOGD_TEAM, "team port %s was released", nm_device_get_ip_iface(slave)); + _LOGI(LOGD_TEAM, "team port %s was detached", nm_device_get_ip_iface(port)); /* Delete any port configuration we previously set */ if (configure && priv->tdc - && (s_port = nm_device_get_applied_setting(slave, NM_TYPE_SETTING_TEAM_PORT)) + && (s_port = nm_device_get_applied_setting(port, NM_TYPE_SETTING_TEAM_PORT)) && (nm_setting_team_port_get_config(s_port))) - teamdctl_port_config_update_raw(priv->tdc, nm_device_get_ip_iface(slave), "{}"); + teamdctl_port_config_update_raw(priv->tdc, nm_device_get_ip_iface(port), "{}"); } static gboolean @@ -1064,8 +1098,8 @@ nm_device_team_class_init(NMDeviceTeamClass *klass) device_class->act_stage1_prepare = act_stage1_prepare; device_class->get_configured_mtu = nm_device_get_configured_mtu_for_wired; device_class->deactivate = deactivate; - device_class->enslave_slave = enslave_slave; - device_class->release_slave = release_slave; + device_class->attach_port = attach_port; + device_class->detach_port = detach_port; obj_properties[PROP_CONFIG] = g_param_spec_string(NM_DEVICE_TEAM_CONFIG, "", diff --git a/src/core/devices/wifi/nm-device-wifi.c b/src/core/devices/wifi/nm-device-wifi.c index 04608d14..39c68d77 100644 --- a/src/core/devices/wifi/nm-device-wifi.c +++ b/src/core/devices/wifi/nm-device-wifi.c @@ -3180,21 +3180,21 @@ ensure_hotspot_frequency(NMDeviceWifi *self, NMSettingWireless *s_wifi, NMWifiAP gsize ssid_len; const guint8 *ssid_data; const guint8 random_seed[16] = {0x9a, - 0xdc, - 0x86, - 0x9a, - 0xa8, - 0xa2, - 0x07, - 0x97, - 0xbe, - 0x6d, - 0xe6, - 0x99, - 0x9f, - 0xa8, - 0x09, - 0x2b}; + 0xdc, + 0x86, + 0x9a, + 0xa8, + 0xa2, + 0x07, + 0x97, + 0xbe, + 0x6d, + 0xe6, + 0x99, + 0x9f, + 0xa8, + 0x09, + 0x2b}; /* Calculate a stable "random" number based on the SSID. */ ssid = nm_setting_wireless_get_ssid(s_wifi); diff --git a/src/core/devices/wifi/tests/test-devices-wifi.c b/src/core/devices/wifi/tests/test-devices-wifi.c index 69d365e3..a52696ea 100644 --- a/src/core/devices/wifi/tests/test-devices-wifi.c +++ b/src/core/devices/wifi/tests/test-devices-wifi.c @@ -412,8 +412,8 @@ test_ap_wpa_psk_connection_base(const char *key_mgmt, const char *ssid = "blahblah"; const char *bssid = "01:02:03:04:05:06"; const KeyData exp_wifi[] = {{NM_SETTING_WIRELESS_SSID, ssid, 0}, - {NM_SETTING_WIRELESS_MODE, "infrastructure", 0}, - {NULL}}; + {NM_SETTING_WIRELESS_MODE, "infrastructure", 0}, + {NULL}}; const KeyData both_wsec[] = {{NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, key_mgmt, 0}, {NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, auth_alg, 0}, {NM_SETTING_WIRELESS_SECURITY_PSK, "asdfasdfasdfasdfasdfafs", 0}, @@ -541,8 +541,8 @@ test_ap_wpa_eap_connection_base(const char *key_mgmt, const char *bssid = "01:02:03:04:05:06"; const KeyData src_empty[] = {{NULL}}; const KeyData src_wsec[] = {{NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, key_mgmt, 0}, - {NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, auth_alg, 0}, - {NULL}}; + {NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, auth_alg, 0}, + {NULL}}; gboolean success; GError *error = NULL; @@ -778,12 +778,12 @@ test_priv_ap_leap_connection_1(gconstpointer add_wifi) const char *bssid = "01:02:03:04:05:06"; const char *leap_username = "Bill Smith"; const KeyData src_wsec[] = {{NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "ieee8021x", 0}, - {NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME, leap_username, 0}, - {NULL}}; + {NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME, leap_username, 0}, + {NULL}}; const KeyData exp_wsec[] = {{NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "ieee8021x", 0}, - {NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "leap", 0}, - {NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME, leap_username, 0}, - {NULL}}; + {NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "leap", 0}, + {NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME, leap_username, 0}, + {NULL}}; gboolean success; GError *error = NULL; @@ -862,15 +862,15 @@ test_priv_ap_dynamic_wep_1(void) const char *ssid = "blahblah"; const char *bssid = "01:02:03:04:05:06"; const KeyData src_wsec[] = {{NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "ieee8021x", 0}, - {NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "open", 0}, - {NULL}}; + {NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "open", 0}, + {NULL}}; const KeyData both_8021x[] = {{NM_SETTING_802_1X_EAP, "peap", 0}, {NM_SETTING_802_1X_IDENTITY, "Bill Smith", 0}, {NM_SETTING_802_1X_PHASE2_AUTH, "mschapv2", 0}, {NULL}}; const KeyData exp_wsec[] = {{NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "ieee8021x", 0}, - {NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "open", 0}, - {NULL}}; + {NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "open", 0}, + {NULL}}; gboolean success; GError *error = NULL; @@ -917,8 +917,8 @@ test_priv_ap_dynamic_wep_2(void) {NM_SETTING_802_1X_PHASE2_AUTH, "mschapv2", 0}, {NULL}}; const KeyData exp_wsec[] = {{NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "ieee8021x", 0}, - {NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "open", 0}, - {NULL}}; + {NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "open", 0}, + {NULL}}; gboolean success; GError *error = NULL; @@ -1130,8 +1130,8 @@ test_wpa_ap_leap_connection_1(gconstpointer data) const char *bssid = "01:02:03:04:05:06"; const char *leap_username = "Bill Smith"; const KeyData src_wsec[] = {{NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "ieee8021x", 0}, - {NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME, leap_username, 0}, - {NULL}}; + {NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME, leap_username, 0}, + {NULL}}; gboolean success; GError *error = NULL; diff --git a/src/core/devices/wwan/nm-modem-ofono.c b/src/core/devices/wwan/nm-modem-ofono.c index 0db30046..c003880e 100644 --- a/src/core/devices/wwan/nm-modem-ofono.c +++ b/src/core/devices/wwan/nm-modem-ofono.c @@ -805,7 +805,7 @@ handle_settings(GVariant *v_dict, gpointer user_data) _LOGW("invalid 'Netmask': %s", s ?: ""); goto out; } - address.plen = nm_utils_ip4_netmask_to_prefix(address_network); + address.plen = _nm_utils_ip4_netmask_to_prefix(address_network); _LOGI("Address: %s", nm_platform_ip4_address_to_string(&address, sbuf, sizeof(sbuf))); nm_l3_config_data_add_address_4(priv->l3cd_4, &address); |