diff --git a/man/NetworkManager.conf.xml b/man/NetworkManager.conf.xml
index 634928f58..9e4429d0f 100644
--- a/man/NetworkManager.conf.xml
+++ b/man/NetworkManager.conf.xml
@@ -935,6 +935,9 @@ ipv6.ip6-privacy=0
ipv4.dhcp-client-id
+
+ ipv4.dhcp-dscp
+
ipv4.dhcp-iaid
If left unspecified, it defaults to "ifname".
diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c
index 74c57b6e4..80a56fbc5 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;
+ };
+
+ 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,
};
diff --git a/src/core/dhcp/nm-dhcp-client.h b/src/core/dhcp/nm-dhcp-client.h
index 4dd2c4fd7..2b262f76c 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 2a3af10a5..043c2264e 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 fc468d4cb..ce1e9a457 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];