summary refs log tree commit diff
path: root/src/core/devices/nm-device-bridge.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/devices/nm-device-bridge.c')
-rw-r--r--src/core/devices/nm-device-bridge.c235
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