diff options
Diffstat (limited to 'src/core/devices/nm-device-bridge.c')
| -rw-r--r-- | src/core/devices/nm-device-bridge.c | 235 |
1 files changed, 120 insertions, 115 deletions
diff --git a/src/core/devices/nm-device-bridge.c b/src/core/devices/nm-device-bridge.c index c5ce34c2..9a45dbf3 100644 --- a/src/core/devices/nm-device-bridge.c +++ b/src/core/devices/nm-device-bridge.c @@ -101,13 +101,16 @@ check_connection_available(NMDevice *device, } static gboolean -check_connection_compatible(NMDevice *device, NMConnection *connection, GError **error) +check_connection_compatible(NMDevice *device, + NMConnection *connection, + gboolean check_properties, + GError **error) { NMSettingBridge *s_bridge; const char *mac_address; if (!NM_DEVICE_CLASS(nm_device_bridge_parent_class) - ->check_connection_compatible(device, connection, error)) + ->check_connection_compatible(device, connection, check_properties, error)) return FALSE; if (nm_connection_is_type(connection, NM_SETTING_BLUETOOTH_SETTING_NAME) @@ -434,96 +437,6 @@ static const Option slave_options[] = { OPTION(NM_SETTING_BRIDGE_PORT_HAIRPIN_MODE, "hairpin_mode", OPTION_TYPE_BOOL(FALSE), ), {0}}; -static void -commit_option(NMDevice *device, NMSetting *setting, const Option *option, gboolean slave) -{ - int ifindex = nm_device_get_ifindex(device); - nm_auto_unset_gvalue GValue val = G_VALUE_INIT; - GParamSpec *pspec; - const char *value; - char value_buf[100]; - - if (slave) - nm_assert(NM_IS_SETTING_BRIDGE_PORT(setting)); - else - nm_assert(NM_IS_SETTING_BRIDGE(setting)); - - pspec = g_object_class_find_property(G_OBJECT_GET_CLASS(setting), option->name); - nm_assert(pspec); - - g_value_init(&val, G_PARAM_SPEC_VALUE_TYPE(pspec)); - g_object_get_property((GObject *) setting, option->name, &val); - - if (option->to_sysfs) { - value = option->to_sysfs(&val); - goto out; - } - - switch (pspec->value_type) { - case G_TYPE_BOOLEAN: - value = g_value_get_boolean(&val) ? "1" : "0"; - break; - case G_TYPE_UINT64: - case G_TYPE_UINT: - { - guint64 uval; - - if (pspec->value_type == G_TYPE_UINT64) - uval = g_value_get_uint64(&val); - else - uval = (guint) g_value_get_uint(&val); - - /* zero means "unspecified" for some NM properties but isn't in the - * allowed kernel range, so reset the property to the default value. - */ - if (option->default_if_zero && uval == 0) { - if (pspec->value_type == G_TYPE_UINT64) - uval = NM_G_PARAM_SPEC_GET_DEFAULT_UINT64(pspec); - else - uval = NM_G_PARAM_SPEC_GET_DEFAULT_UINT(pspec); - } - - /* Linux kernel bridge interfaces use 'centiseconds' for time-based values. - * In reality it's not centiseconds, but depends on HZ and USER_HZ, which - * is almost always works out to be a multiplier of 100, so we can assume - * centiseconds. See clock_t_to_jiffies(). - */ - if (option->user_hz_compensate) - uval *= 100; - - if (pspec->value_type == G_TYPE_UINT64) - nm_sprintf_buf(value_buf, "%" G_GUINT64_FORMAT, uval); - else - nm_sprintf_buf(value_buf, "%u", (guint) uval); - - value = value_buf; - } break; - case G_TYPE_STRING: - value = g_value_get_string(&val); - break; - default: - nm_assert_not_reached(); - value = NULL; - break; - } - -out: - if (!value) - return; - - if (slave) { - nm_platform_sysctl_slave_set_option(nm_device_get_platform(device), - ifindex, - option->sysname, - value); - } else { - nm_platform_sysctl_master_set_option(nm_device_get_platform(device), - ifindex, - option->sysname, - value); - } -} - static const NMPlatformBridgeVlan ** setting_vlans_to_platform(GPtrArray *array) { @@ -558,19 +471,92 @@ setting_vlans_to_platform(GPtrArray *array) } static void -commit_slave_options(NMDevice *device, NMSettingBridgePort *setting) +commit_port_options(NMDevice *device, NMSettingBridgePort *setting) { const Option *option; NMSetting *s; gs_unref_object NMSetting *s_clear = NULL; + int ifindex = nm_device_get_ifindex(device); if (setting) s = NM_SETTING(setting); else s = s_clear = nm_setting_bridge_port_new(); - for (option = slave_options; option->name; option++) - commit_option(device, s, option, TRUE); + for (option = slave_options; option->name; option++) { + nm_auto_unset_gvalue GValue val = G_VALUE_INIT; + GParamSpec *pspec; + const char *value; + char value_buf[100]; + + pspec = g_object_class_find_property(G_OBJECT_GET_CLASS(s), option->name); + nm_assert(pspec); + + g_value_init(&val, G_PARAM_SPEC_VALUE_TYPE(pspec)); + g_object_get_property((GObject *) s, option->name, &val); + + if (option->to_sysfs) { + value = option->to_sysfs(&val); + goto out; + } + + switch (pspec->value_type) { + case G_TYPE_BOOLEAN: + value = g_value_get_boolean(&val) ? "1" : "0"; + break; + case G_TYPE_UINT64: + case G_TYPE_UINT: + { + guint64 uval; + + if (pspec->value_type == G_TYPE_UINT64) + uval = g_value_get_uint64(&val); + else + uval = (guint) g_value_get_uint(&val); + + /* zero means "unspecified" for some NM properties but isn't in the + * allowed kernel range, so reset the property to the default value. + */ + if (option->default_if_zero && uval == 0) { + if (pspec->value_type == G_TYPE_UINT64) + uval = NM_G_PARAM_SPEC_GET_DEFAULT_UINT64(pspec); + else + uval = NM_G_PARAM_SPEC_GET_DEFAULT_UINT(pspec); + } + + /* Linux kernel bridge interfaces use 'centiseconds' for time-based values. + * In reality it's not centiseconds, but depends on HZ and USER_HZ, which + * is almost always works out to be a multiplier of 100, so we can assume + * centiseconds. See clock_t_to_jiffies(). + */ + if (option->user_hz_compensate) + uval *= 100; + + if (pspec->value_type == G_TYPE_UINT64) + nm_sprintf_buf(value_buf, "%" G_GUINT64_FORMAT, uval); + else + nm_sprintf_buf(value_buf, "%u", (guint) uval); + + value = value_buf; + } break; + case G_TYPE_STRING: + value = g_value_get_string(&val); + break; + default: + nm_assert_not_reached(); + value = NULL; + break; + } + +out: + if (!value) + return; + + nm_platform_sysctl_slave_set_option(nm_device_get_platform(device), + ifindex, + option->sysname, + value); + } } static void @@ -746,8 +732,13 @@ bridge_set_vlan_options(NMDevice *device, NMSettingBridge *s_bridge) enabled = nm_setting_bridge_get_vlan_filtering(s_bridge); if (!enabled) { - nm_platform_sysctl_master_set_option(plat, ifindex, "vlan_filtering", "0"); - nm_platform_sysctl_master_set_option(plat, ifindex, "default_pvid", "1"); + nm_platform_link_set_bridge_info( + plat, + ifindex, + &((NMPlatformLinkSetBridgeInfoData){.vlan_filtering_has = TRUE, + .vlan_filtering_val = FALSE, + .vlan_default_pvid_has = TRUE, + .vlan_default_pvid_val = 1})); nm_platform_link_set_bridge_vlans(plat, ifindex, FALSE, NULL); return TRUE; } @@ -762,14 +753,17 @@ bridge_set_vlan_options(NMDevice *device, NMSettingBridge *s_bridge) self->vlan_configured = TRUE; - /* Filtering must be disabled to change the default PVID */ - if (!nm_platform_sysctl_master_set_option(plat, ifindex, "vlan_filtering", "0")) - return FALSE; - - /* Clear the default PVID so that we later can force the re-creation of + /* Filtering must be disabled to change the default PVID. + * Clear the default PVID so that we later can force the re-creation of * default PVID VLANs by writing the option again. */ - if (!nm_platform_sysctl_master_set_option(plat, ifindex, "default_pvid", "0")) - return FALSE; + + nm_platform_link_set_bridge_info( + plat, + ifindex, + &((NMPlatformLinkSetBridgeInfoData){.vlan_filtering_has = TRUE, + .vlan_filtering_val = FALSE, + .vlan_default_pvid_has = TRUE, + .vlan_default_pvid_val = 0})); /* Clear all existing VLANs */ if (!nm_platform_link_set_bridge_vlans(plat, ifindex, FALSE, NULL)) @@ -779,11 +773,11 @@ bridge_set_vlan_options(NMDevice *device, NMSettingBridge *s_bridge) * a PVID VLAN on each port, including the bridge itself. */ pvid = nm_setting_bridge_get_vlan_default_pvid(s_bridge); if (pvid) { - char value[32]; - - nm_sprintf_buf(value, "%u", pvid); - if (!nm_platform_sysctl_master_set_option(plat, ifindex, "default_pvid", value)) - return FALSE; + nm_platform_link_set_bridge_info( + plat, + ifindex, + &((NMPlatformLinkSetBridgeInfoData){.vlan_default_pvid_has = TRUE, + .vlan_default_pvid_val = pvid})); } /* Create VLANs only after setting the default PVID, so that @@ -793,8 +787,12 @@ bridge_set_vlan_options(NMDevice *device, NMSettingBridge *s_bridge) if (plat_vlans && !nm_platform_link_set_bridge_vlans(plat, ifindex, FALSE, plat_vlans)) return FALSE; - if (!nm_platform_sysctl_master_set_option(plat, ifindex, "vlan_filtering", "1")) - return FALSE; + nm_platform_link_set_bridge_info(plat, + ifindex, + &((NMPlatformLinkSetBridgeInfoData){ + .vlan_filtering_has = TRUE, + .vlan_filtering_val = TRUE, + })); return TRUE; } @@ -1027,7 +1025,7 @@ attach_port(NMDevice *device, return FALSE; } - commit_slave_options(port, s_port); + commit_port_options(port, s_port); _LOGI(LOGD_BRIDGE, "attached bridge port %s", nm_device_get_ip_iface(port)); } else { @@ -1037,8 +1035,13 @@ attach_port(NMDevice *device, return TRUE; } -static void -detach_port(NMDevice *device, NMDevice *port, gboolean configure) +static NMTernary +detach_port(NMDevice *device, + NMDevice *port, + gboolean configure, + GCancellable *cancellable, + NMDeviceAttachPortCallback callback, + gpointer user_data) { NMDeviceBridge *self = NM_DEVICE_BRIDGE(device); gboolean success; @@ -1055,7 +1058,7 @@ detach_port(NMDevice *device, NMDevice *port, gboolean configure) if (ifindex_slave <= 0) { _LOGD(LOGD_TEAM, "bridge port %s is already detached", nm_device_get_ip_iface(port)); - return; + return TRUE; } if (configure) { @@ -1071,6 +1074,8 @@ detach_port(NMDevice *device, NMDevice *port, gboolean configure) } else { _LOGI(LOGD_BRIDGE, "bridge port %s was detached", nm_device_get_ip_iface(port)); } + + return TRUE; } static gboolean |