From: Oliver Chen Date: Wed, 16 Apr 2025 03:36:05 +0000 (+0000) Subject: Support DSCP marking towards downstream server X-Git-Tag: dnsdist-2.0.0-alpha2~57^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8983a1feb4a6ca26da80943ce70ec20de4565da6;p=thirdparty%2Fpdns.git Support DSCP marking towards downstream server --- diff --git a/pdns/dnsdistdist/dnsdist-backend.cc b/pdns/dnsdistdist/dnsdist-backend.cc index 31e9d254cd..d1f144ee22 100644 --- a/pdns/dnsdistdist/dnsdist-backend.cc +++ b/pdns/dnsdistdist/dnsdist-backend.cc @@ -140,6 +140,7 @@ bool DownstreamState::reconnect(bool initialAttempt) } try { + setDscp(fd, d_config.remote.sin4.sin_family, d_config.dscp); SConnect(fd, d_config.remote); if (sockets.size() > 1) { (*mplexer.lock())->addReadFD(fd, [](int, boost::any) {}); diff --git a/pdns/dnsdistdist/dnsdist-configuration-yaml.cc b/pdns/dnsdistdist/dnsdist-configuration-yaml.cc index 459552af32..475a75660c 100644 --- a/pdns/dnsdistdist/dnsdist-configuration-yaml.cc +++ b/pdns/dnsdistdist/dnsdist-configuration-yaml.cc @@ -507,6 +507,8 @@ static std::shared_ptr createBackendFromConfiguration(const dns dnsdist::ServiceDiscovery::addUpgradeableServer(downstream, autoUpgradeConf.interval, std::string(autoUpgradeConf.pool), autoUpgradeConf.doh_key, autoUpgradeConf.keep); } + backendConfig.dscp = config.dscp; + return downstream; } diff --git a/pdns/dnsdistdist/dnsdist-lua.cc b/pdns/dnsdistdist/dnsdist-lua.cc index 3504cbd6a4..f52ae0cfe2 100644 --- a/pdns/dnsdistdist/dnsdist-lua.cc +++ b/pdns/dnsdistdist/dnsdist-lua.cc @@ -503,6 +503,7 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) getOptionalValue(vars, "enableRenegotiation", config.d_tlsParams.d_enableRenegotiation); getOptionalValue(vars, "ktls", config.d_tlsParams.d_ktls); getOptionalValue(vars, "subjectName", config.d_tlsSubjectName); + getOptionalIntegerValue("newServer", vars, "dscp", config.dscp); if (vars->count("keyLogFile") > 0) { #ifdef HAVE_SSL_CTX_SET_KEYLOG_CALLBACK diff --git a/pdns/dnsdistdist/dnsdist-rust-lib/rust/src/lib.rs b/pdns/dnsdistdist/dnsdist-rust-lib/rust/src/lib.rs index be2411ba96..cdab005007 100644 --- a/pdns/dnsdistdist/dnsdist-rust-lib/rust/src/lib.rs +++ b/pdns/dnsdistdist/dnsdist-rust-lib/rust/src/lib.rs @@ -1844,6 +1844,8 @@ mod dnsdistsettings { cpus: String, #[serde(default, skip_serializing_if = "crate::is_default")] xsk: String, + #[serde(default, skip_serializing_if = "crate::is_default")] + dscp: u8, } #[derive(Deserialize, Serialize, Debug, PartialEq)] diff --git a/pdns/dnsdistdist/dnsdist-settings-definitions.yml b/pdns/dnsdistdist/dnsdist-settings-definitions.yml index a00387a0e1..fd1de4234f 100644 --- a/pdns/dnsdistdist/dnsdist-settings-definitions.yml +++ b/pdns/dnsdistdist/dnsdist-settings-definitions.yml @@ -1425,6 +1425,10 @@ backend: type: "String" default: "" description: "The name of an XSK sockets map to attach to this frontend, if any" + - name: "dscp" + type: "u8" + default: 0 + description: "The DSCP marking value to be applied. Range 0-63. Default is 0 which means no action for DSCP marking." tuning: description: "Tuning settings" diff --git a/pdns/dnsdistdist/dnsdist-tcp-downstream.cc b/pdns/dnsdistdist/dnsdist-tcp-downstream.cc index 5c1335438b..1c91bba137 100644 --- a/pdns/dnsdistdist/dnsdist-tcp-downstream.cc +++ b/pdns/dnsdistdist/dnsdist-tcp-downstream.cc @@ -81,6 +81,7 @@ bool ConnectionToBackend::reconnect() the other end to acknowledge our initial packet before we could send the rest. */ setTCPNoDelay(socket.getHandle()); + setDscp(socket.getHandle(), d_ds->d_config.remote.sin4.sin_family, d_ds->d_config.dscp); #ifdef SO_BINDTODEVICE if (!d_ds->d_config.sourceItfName.empty()) { diff --git a/pdns/dnsdistdist/dnsdist.hh b/pdns/dnsdistdist/dnsdist.hh index 56ee6e8042..866c878725 100644 --- a/pdns/dnsdistdist/dnsdist.hh +++ b/pdns/dnsdistdist/dnsdist.hh @@ -592,6 +592,7 @@ struct DownstreamState : public std::enable_shared_from_this uint8_t maxCheckFailures{1}; uint8_t minRiseSuccesses{1}; uint8_t udpTimeout{0}; + uint8_t dscp{0}; Availability availability{Availability::Auto}; bool d_tlsSubjectIsAddr{false}; bool mustResolve{false}; diff --git a/pdns/dnsdistdist/docs/reference/config.rst b/pdns/dnsdistdist/docs/reference/config.rst index 870129bc48..b8f8eab9d9 100644 --- a/pdns/dnsdistdist/docs/reference/config.rst +++ b/pdns/dnsdistdist/docs/reference/config.rst @@ -759,6 +759,7 @@ Servers ``xskSockets`` ``array`` "An array of :class:`XskSocket` objects to enable ``XSK`` / ``AF_XDP`` support for this backend. See :doc:`../advanced/xsk` for more information." ``MACAddr`` ``str`` "When the ``xskSocket`` option is set, this parameter can be used to specify the destination MAC address to use to reach the backend. If this options is not specified, dnsdist will try to get it from the IP of the backend by looking into the system's MAC address table, but it will fail if the corresponding MAC address is not present." ``keyLogFile`` ``str`` "Write the TLS keys in the specified file so that an external program can decrypt TLS exchanges, in the format described in https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format. Note that this feature requires OpenSSL >= 1.1.1." + ``dscp`` ``number`` "The DSCP marking value to be applied. Range 0-63. Default is 0 which means no action for DSCP marking." .. function:: getServer(index) -> Server diff --git a/pdns/dnsdistdist/docs/reference/yaml-settings.rst b/pdns/dnsdistdist/docs/reference/yaml-settings.rst index 8876dd6075..c594c491c1 100644 --- a/pdns/dnsdistdist/docs/reference/yaml-settings.rst +++ b/pdns/dnsdistdist/docs/reference/yaml-settings.rst @@ -101,6 +101,7 @@ Generic settings for backends - **mac_address**: String ``("")`` - When the ``xsk`` option is set, this parameter can be used to specify the destination MAC address to use to reach the backend. If this options is not specified, dnsdist will try to get it from the IP of the backend by looking into the system's MAC address table, but it will fail if the corresponding MAC address is not present - **cpus**: String ``("")`` - Set the CPU affinity for this thread, asking the scheduler to run it on a single CPU id, or a set of CPU ids. This parameter is only available if the OS provides the ``pthread_setaffinity_np()`` function - **xsk**: String ``("")`` - The name of an XSK sockets map to attach to this frontend, if any +- **dscp**: Unsigned integer ``(0)`` - The DSCP marking value to be applied. Range 0-63. Default is 0 which means no action for DSCP marking. .. _yaml-settings-BindConfiguration: diff --git a/pdns/misc.cc b/pdns/misc.cc index a64f00a5fe..26335e9203 100644 --- a/pdns/misc.cc +++ b/pdns/misc.cc @@ -1082,6 +1082,36 @@ bool setReuseAddr(int sock) return true; } +void setDscp(int sock, unsigned short family, uint8_t dscp) +{ + int val; + unsigned int len; + + if (dscp == 0 || dscp > 63) { + // No DSCP marking + return; + } + + if (family == AF_INET) { + if (getsockopt(sock, IPPROTO_IP, IP_TOS, &val, &len)<0) { + throw std::runtime_error(string("Set DSCP failed: ")+stringerror()); + } + val = (dscp<<2) | (val&0x3); + if (setsockopt(sock, IPPROTO_IP, IP_TOS, &val, sizeof(val))<0) { + throw std::runtime_error(string("Set DSCP failed: ")+stringerror()); + } + } + else if (family == AF_INET6) { + if (getsockopt(sock, IPPROTO_IPV6, IPV6_TCLASS, &val, &len)<0) { + throw std::runtime_error(string("Set DSCP failed: ")+stringerror()); + } + val = (dscp<<2) | (val&0x3); + if (setsockopt(sock, IPPROTO_IPV6, IPV6_TCLASS, &val, sizeof(val))<0) { + throw std::runtime_error(string("Set DSCP failed: ")+stringerror()); + } + } +} + bool isNonBlocking(int sock) { int flags=fcntl(sock,F_GETFL,0); diff --git a/pdns/misc.hh b/pdns/misc.hh index 6129d37664..6b1c70cf24 100644 --- a/pdns/misc.hh +++ b/pdns/misc.hh @@ -593,6 +593,8 @@ bool setSocketTimestamps(int fd); //! Sets the socket into blocking mode. bool setBlocking( int sock ); +void setDscp(int sock, unsigned short family, uint8_t dscp); + //! Sets the socket into non-blocking mode. bool setNonBlocking( int sock ); bool setTCPNoDelay(int sock);