about summary refs log tree commit diff
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/devices/nm-device-bridge.c79
-rw-r--r--src/core/devices/nm-device.c52
-rw-r--r--src/core/dhcp/nm-dhcp-client.h7
-rw-r--r--src/core/dhcp/nm-dhcp-dhclient.c5
-rw-r--r--src/core/dhcp/nm-dhcp-nettools.c2
-rw-r--r--src/core/nm-manager.c12
-rw-r--r--src/core/platform/tests/test-link.c2
-rw-r--r--src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c13
8 files changed, 137 insertions, 35 deletions
diff --git a/src/core/devices/nm-device-bridge.c b/src/core/devices/nm-device-bridge.c
index 193b655c..ab3a6be9 100644
--- a/src/core/devices/nm-device-bridge.c
+++ b/src/core/devices/nm-device-bridge.c
@@ -619,7 +619,27 @@ master_update_slave_connection(NMDevice     *device,
 }
 
 static gboolean
-bridge_set_vlan_options(NMDevice *device, NMSettingBridge *s_bridge)
+is_bridge_pvid_changed(NMDevice *device, NMSettingBridge *s_bridge)
+{
+    int                        ifindex = nm_device_get_ifindex(device);
+    const NMPlatformLnkBridge *nmp_link_br;
+    NMPlatform                *platform = nm_device_get_platform(device);
+    bool    desired_vlan_filtering      = nm_setting_bridge_get_vlan_filtering(s_bridge);
+    guint16 desired_pvid                = nm_setting_bridge_get_vlan_default_pvid(s_bridge);
+
+    nm_platform_link_refresh(platform, ifindex);
+    nmp_link_br = nm_platform_link_get_lnk_bridge(platform, ifindex, NULL);
+
+    if (nmp_link_br) {
+        return desired_vlan_filtering != nmp_link_br->vlan_filtering
+               || desired_pvid != nmp_link_br->default_pvid;
+    } else {
+        return TRUE;
+    }
+}
+
+static gboolean
+bridge_set_vlan_options(NMDevice *device, NMSettingBridge *s_bridge, gboolean is_reapply)
 {
     NMDeviceBridge                      *self = NM_DEVICE_BRIDGE(device);
     gconstpointer                        hwaddr;
@@ -660,31 +680,37 @@ bridge_set_vlan_options(NMDevice *device, NMSettingBridge *s_bridge)
 
     self->vlan_configured = TRUE;
 
-    /* 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 (!is_reapply || is_bridge_pvid_changed(device, s_bridge)) {
+        /* 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. */
 
-    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))
-        return FALSE;
+        if (is_reapply) {
+            _LOGD(LOGD_BRIDGE, "default_pvid is changed, resetting bridge VLAN filtering");
+        }
 
-    /* Now set the default PVID. After this point the kernel creates
-     * a PVID VLAN on each port, including the bridge itself. */
-    pvid = nm_setting_bridge_get_vlan_default_pvid(s_bridge);
-    if (pvid) {
         nm_platform_link_set_bridge_info(
             plat,
             ifindex,
-            &((NMPlatformLinkSetBridgeInfoData){.vlan_default_pvid_has = TRUE,
-                                                .vlan_default_pvid_val = pvid}));
+            &((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))
+            return FALSE;
+
+        /* Now set the default PVID. After this point the kernel creates
+         * a PVID VLAN on each port, including the bridge itself. */
+        pvid = nm_setting_bridge_get_vlan_default_pvid(s_bridge);
+        if (pvid) {
+            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
@@ -743,7 +769,7 @@ _platform_lnk_bridge_init_from_setting(NMSettingBridge *s_bridge, NMPlatformLnkB
 }
 
 static gboolean
-link_config(NMDevice *device, NMConnection *connection)
+link_config(NMDevice *device, NMConnection *connection, gboolean is_reapply)
 {
     int                 ifindex = nm_device_get_ifindex(device);
     NMSettingBridge    *s_bridge;
@@ -757,7 +783,7 @@ link_config(NMDevice *device, NMConnection *connection)
     if (nm_platform_link_bridge_change(nm_device_get_platform(device), ifindex, &props) < 0)
         return FALSE;
 
-    return bridge_set_vlan_options(device, s_bridge);
+    return bridge_set_vlan_options(device, s_bridge, is_reapply);
 }
 
 static NMActStageReturn
@@ -768,7 +794,7 @@ act_stage1_prepare(NMDevice *device, NMDeviceStateReason *out_failure_reason)
     connection = nm_device_get_applied_connection(device);
     g_return_val_if_fail(connection, NM_ACT_STAGE_RETURN_FAILURE);
 
-    if (!link_config(device, connection)) {
+    if (!link_config(device, connection, FALSE)) {
         NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_CONFIG_FAILED);
         return NM_ACT_STAGE_RETURN_FAILURE;
     }
@@ -910,7 +936,7 @@ attach_port(NMDevice                  *device,
         s_port = nm_connection_get_setting_bridge_port(connection);
 
         if (!nm_device_sys_iface_state_is_external(device))
-            bridge_set_vlan_options(device, s_bridge);
+            bridge_set_vlan_options(device, s_bridge, FALSE);
 
         if (nm_setting_bridge_get_vlan_filtering(s_bridge)) {
             gs_free const NMPlatformBridgeVlan **plat_vlans = NULL;
@@ -1125,8 +1151,7 @@ reapply_connection(NMDevice *device, NMConnection *con_old, NMConnection *con_ne
     /* 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);
+    link_config(device, con_new, TRUE);
 }
 
 /*****************************************************************************/
diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c
index 16f8e1f2..a9e8c085 100644
--- a/src/core/devices/nm-device.c
+++ b/src/core/devices/nm-device.c
@@ -2185,6 +2185,52 @@ out_good:
     return result;
 }
 
+static guint8
+_prop_get_ipv4_dhcp_dscp(NMDevice *self, gboolean *out_dscp_explicit)
+{
+    gs_free_error GError *error = NULL;
+    NMConnection         *connection;
+    NMSettingIPConfig    *s_ip;
+    const char           *str;
+
+    connection = nm_device_get_applied_connection(self);
+    s_ip       = nm_connection_get_setting_ip_config(connection, AF_INET);
+    g_return_val_if_fail(s_ip, 0);
+
+    NM_SET_OUT(out_dscp_explicit, TRUE);
+
+    str = nm_setting_ip_config_get_dhcp_dscp(s_ip);
+    if (str) {
+        nm_assert(nm_utils_validate_dhcp_dscp(str, NULL));
+    } else {
+        str = nm_config_data_get_connection_default(NM_CONFIG_GET_DATA,
+                                                    NM_CON_DEFAULT("ipv4.dhcp-dscp"),
+                                                    self);
+        if (!str || !str[0]) {
+            str = "CS0";
+            NM_SET_OUT(out_dscp_explicit, FALSE);
+        } else if (!nm_utils_validate_dhcp_dscp(str, &error)) {
+            _LOGW(LOGD_DEVICE,
+                  "invalid global default value '%s' for ipv4.%s: %s",
+                  str,
+                  NM_SETTING_IP_CONFIG_DHCP_DSCP,
+                  error->message);
+            str = "CS0";
+            NM_SET_OUT(out_dscp_explicit, FALSE);
+        }
+    }
+
+    if (nm_streq(str, "CS0")) {
+        return 0;
+    } else if (nm_streq(str, "CS6")) {
+        return 0x30;
+    } else if (nm_streq(str, "CS4")) {
+        return 0x20;
+    };
+
+    return nm_assert_unreachable_val(0);
+}
+
 static GBytes *
 _prop_get_ipv4_dhcp_vendor_class_identifier(NMDevice *self, NMSettingIP4Config *s_ip4)
 {
@@ -10970,8 +11016,11 @@ _dev_ipdhcpx_start(NMDevice *self, int addr_family)
         const char            *hostname;
         gboolean               hostname_is_fqdn;
         gboolean               send_client_id;
+        guint8                 dscp;
+        gboolean               dscp_explicit = FALSE;
 
         client_id = _prop_get_ipv4_dhcp_client_id(self, connection, hwaddr, &send_client_id);
+        dscp      = _prop_get_ipv4_dhcp_dscp(self, &dscp_explicit);
 
         vendor_class_identifier =
             _prop_get_ipv4_dhcp_vendor_class_identifier(self, NM_SETTING_IP4_CONFIG(s_ip));
@@ -11010,6 +11059,8 @@ _dev_ipdhcpx_start(NMDevice *self, int addr_family)
                     .request_broadcast = request_broadcast,
                     .acd_timeout_msec  = _prop_get_ipv4_dad_timeout(self),
                     .send_client_id    = send_client_id,
+                    .dscp              = dscp,
+                    .dscp_explicit     = dscp_explicit,
                 },
             .previous_lease = priv->l3cds[L3_CONFIG_DATA_TYPE_DHCP_X(IS_IPv4)].d,
         };
@@ -13369,6 +13420,7 @@ can_reapply_change(NMDevice   *self,
                                                  NM_SETTING_CONNECTION_STABLE_ID,
                                                  NM_SETTING_CONNECTION_AUTOCONNECT,
                                                  NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES,
+                                                 NM_SETTING_CONNECTION_AUTOCONNECT_PORTS,
                                                  NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY,
                                                  NM_SETTING_CONNECTION_ZONE,
                                                  NM_SETTING_CONNECTION_METERED,
diff --git a/src/core/dhcp/nm-dhcp-client.h b/src/core/dhcp/nm-dhcp-client.h
index 4dd2c4fd..2b262f76 100644
--- a/src/core/dhcp/nm-dhcp-client.h
+++ b/src/core/dhcp/nm-dhcp-client.h
@@ -158,6 +158,13 @@ typedef struct {
              * is disabled. */
             guint acd_timeout_msec;
 
+            /* The DSCP value to use */
+            guint8 dscp;
+
+            /* Whether the DSCP value is explicitly set (or it is the default
+             * one) */
+            bool dscp_explicit : 1;
+
             /* Set BOOTP broadcast flag in request packets, so that servers
              * will always broadcast replies. */
             bool request_broadcast : 1;
diff --git a/src/core/dhcp/nm-dhcp-dhclient.c b/src/core/dhcp/nm-dhcp-dhclient.c
index 2a3af10a..043c2264 100644
--- a/src/core/dhcp/nm-dhcp-dhclient.c
+++ b/src/core/dhcp/nm-dhcp-dhclient.c
@@ -457,6 +457,11 @@ dhclient_start(NMDhcpClient *client,
         g_ptr_array_add(argv, (gpointer) priv->conf_file);
     }
 
+    if (client_config->v4.dscp_explicit) {
+        _LOGW("dhclient does not support specifying a custom DSCP value; the TOS field will be set "
+              "to LOWDELAY (0x10).");
+    }
+
     /* Usually the system bus address is well-known; but if it's supposed
      * to be something else, we need to push it to dhclient, since dhclient
      * sanitizes the environment it gives the action scripts.
diff --git a/src/core/dhcp/nm-dhcp-nettools.c b/src/core/dhcp/nm-dhcp-nettools.c
index fc468d4c..ce1e9a45 100644
--- a/src/core/dhcp/nm-dhcp-nettools.c
+++ b/src/core/dhcp/nm-dhcp-nettools.c
@@ -1388,6 +1388,8 @@ ip4_start(NMDhcpClient *client, GError **error)
         }
     }
 
+    n_dhcp4_client_probe_config_set_dscp(config, client_config->v4.dscp);
+
     if (client_config->hostname) {
         if (client_config->use_fqdn) {
             uint8_t             buffer[255];
diff --git a/src/core/nm-manager.c b/src/core/nm-manager.c
index 9c58a47d..2cf9cb1d 100644
--- a/src/core/nm-manager.c
+++ b/src/core/nm-manager.c
@@ -5333,14 +5333,14 @@ find_slaves(NMManager            *manager,
 static gboolean
 should_connect_slaves(NMConnection *connection, NMDevice *device)
 {
-    NMSettingConnection                 *s_con;
-    NMSettingConnectionAutoconnectSlaves val;
+    NMSettingConnection *s_con;
+    NMTernary            val;
 
     s_con = nm_connection_get_setting_connection(connection);
     g_assert(s_con);
 
-    val = nm_setting_connection_get_autoconnect_slaves(s_con);
-    if (val != NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES_DEFAULT)
+    val = nm_setting_connection_get_autoconnect_ports(s_con);
+    if (val != NM_TERNARY_DEFAULT)
         goto out;
 
     val =
@@ -5352,9 +5352,9 @@ should_connect_slaves(NMConnection *connection, NMDevice *device)
                                                     -1);
 
 out:
-    if (val == NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES_NO)
+    if (val == NM_TERNARY_FALSE)
         return FALSE;
-    if (val == NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES_YES)
+    if (val == NM_TERNARY_TRUE)
         return TRUE;
     return FALSE;
 }
diff --git a/src/core/platform/tests/test-link.c b/src/core/platform/tests/test-link.c
index c931605b..205559ce 100644
--- a/src/core/platform/tests/test-link.c
+++ b/src/core/platform/tests/test-link.c
@@ -1424,6 +1424,8 @@ test_software_detect(gconstpointer user_data)
         lnk_bridge.mcast_query_interval          = 12000;
         lnk_bridge.mcast_query_response_interval = 5200;
         lnk_bridge.mcast_startup_query_interval  = 3000;
+        lnk_bridge.vlan_filtering                = FALSE;
+        lnk_bridge.default_pvid                  = 1;
 
         if (!nmtstp_link_bridge_add(NULL, ext, DEVICE_NAME, &lnk_bridge))
             g_error("Failed adding Bridge interface");
diff --git a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c
index e703bb73..07e5e64d 100644
--- a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c
+++ b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c
@@ -3360,6 +3360,8 @@ do_write_construct(NMConnection                   *connection,
                    GError                        **error)
 {
     NMSettingConnection                *s_con;
+    NMSettingIPConfig                  *s_ip4;
+    NMSettingIPConfig                  *s_ip6;
     nm_auto_shvar_file_close shvarFile *ifcfg = NULL;
     const char                         *ifcfg_name;
     gs_free char                       *ifcfg_name_free = NULL;
@@ -3546,8 +3548,6 @@ do_write_construct(NMConnection                   *connection,
     has_complex_routes_v6 = utils_has_complex_routes(ifcfg_name, AF_INET6);
 
     if (has_complex_routes_v4 || has_complex_routes_v6) {
-        NMSettingIPConfig *s_ip4, *s_ip6;
-
         s_ip4 = nm_connection_get_setting_ip4_config(connection);
         s_ip6 = nm_connection_get_setting_ip6_config(connection);
         if ((s_ip4 && nm_setting_ip_config_get_num_routes(s_ip4) > 0)
@@ -3584,6 +3584,15 @@ do_write_construct(NMConnection                   *connection,
     } else
         route_ignore = FALSE;
 
+    if ((s_ip4 = nm_connection_get_setting_ip4_config(connection))
+        && nm_setting_ip_config_get_dhcp_dscp(s_ip4)) {
+        set_error_unsupported(error,
+                              connection,
+                              NM_SETTING_IP4_CONFIG_SETTING_NAME "." NM_SETTING_IP_CONFIG_DHCP_DSCP,
+                              FALSE);
+        return FALSE;
+    }
+
     write_ip4_setting(connection,
                       ifcfg,
                       !route_ignore && route_path_is_svformat ? &route_content_svformat : NULL,