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];