From: Pieter Lexis Date: Fri, 17 Oct 2025 11:46:16 +0000 (+0200) Subject: feat(dnsdist): Also send delayed protobuf for TCP queries X-Git-Tag: rec-5.4.0-alpha1~179^2~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=016cef86f85801d11c4054eb91beecdad4f3a06d;p=thirdparty%2Fpdns.git feat(dnsdist): Also send delayed protobuf for TCP queries This commit makes some changes to how delayed messages are sent. We now store the raw, serialized DNSMessage protobuf data in the id-state object when a send delay is needed. When the delayed protobuf has to be sent, we generate the OpenTelemetry Trace data and append it to the message to be sent. --- diff --git a/pdns/dnsdistdist/dnsdist-actions-factory.cc b/pdns/dnsdistdist/dnsdist-actions-factory.cc index 610bd46879..28af79c4ef 100644 --- a/pdns/dnsdistdist/dnsdist-actions-factory.cc +++ b/pdns/dnsdistdist/dnsdist-actions-factory.cc @@ -1861,16 +1861,18 @@ public: (*d_alterFunc)(response, &message); } + static thread_local std::string data; + data.clear(); + message.serialize(data, !d_delay); + + if (!response->ids.d_rawProtobufContent.empty()) { + data.insert(data.end(), response->ids.d_rawProtobufContent.begin(), response->ids.d_rawProtobufContent.end()); + } + if (d_delay) { - response->ids.delayedResponseMsgs.emplace_back(std::unique_ptr(std::make_unique(message)), std::shared_ptr(d_logger)); + response->ids.delayedResponseMsgs.emplace_back(data, std::shared_ptr(d_logger)); } else { - static thread_local std::string data; - data.clear(); - message.serialize(data); - if (!response->ids.d_rawProtobufContent.empty()) { - data.insert(data.end(), response->ids.d_rawProtobufContent.begin(), response->ids.d_rawProtobufContent.end()); - } d_logger->queueData(data); } diff --git a/pdns/dnsdistdist/dnsdist-idstate.cc b/pdns/dnsdistdist/dnsdist-idstate.cc index 62a108beaa..30fa8761ec 100644 --- a/pdns/dnsdistdist/dnsdist-idstate.cc +++ b/pdns/dnsdistdist/dnsdist-idstate.cc @@ -57,3 +57,26 @@ InternalQueryState InternalQueryState::partialCloneForXFR() const #endif return ids; } + +void InternalQueryState::sendDelayedProtobufMessages() const +{ +#ifndef DISABLE_PROTOBUF + static thread_local string otPBBuf; + otPBBuf.clear(); + if (tracingEnabled) { + pdns::ProtoZero::Message msg{otPBBuf}; + msg.setOpenTelemetryData(d_OTTracer->getOTProtobuf()); + } + + for (auto const& msg_logger : delayedResponseMsgs) { + // TODO: we should probably do something with the return value of queueData + if (!tracingEnabled) { + msg_logger.second->queueData(msg_logger.first); + continue; + } + // Protobuf wireformat allows us to simply append the second "message" + // that only contains the OTTrace data as a single bytes field + msg_logger.second->queueData(msg_logger.first + otPBBuf); + } +#endif +} diff --git a/pdns/dnsdistdist/dnsdist-idstate.hh b/pdns/dnsdistdist/dnsdist-idstate.hh index 972c4c6f74..c802503aae 100644 --- a/pdns/dnsdistdist/dnsdist-idstate.hh +++ b/pdns/dnsdistdist/dnsdist-idstate.hh @@ -162,6 +162,8 @@ struct InternalQueryState #endif /* HAVE_XSK */ } + void sendDelayedProtobufMessages() const; + InternalQueryState partialCloneForXFR() const; boost::optional subnet{boost::none}; // 40 @@ -188,7 +190,7 @@ public: std::unique_ptr d_packet{nullptr}; // Initial packet, so we can restart the query from the response path if needed // 8 std::unique_ptr d_protoBufData{nullptr}; #ifndef DISABLE_PROTOBUF - std::vector, std::shared_ptr>> delayedResponseMsgs; + std::vector>> delayedResponseMsgs; #endif std::unique_ptr d_extendedError{nullptr}; boost::optional tempFailureTTL{boost::none}; // 8 diff --git a/pdns/dnsdistdist/dnsdist-protobuf.cc b/pdns/dnsdistdist/dnsdist-protobuf.cc index 2f984fc92b..bb039ef018 100644 --- a/pdns/dnsdistdist/dnsdist-protobuf.cc +++ b/pdns/dnsdistdist/dnsdist-protobuf.cc @@ -125,7 +125,7 @@ void DNSDistProtoBufMessage::addRR(DNSName&& qname, uint16_t uType, uint16_t uCl d_additionalRRs.push_back({std::move(qname), strBlob, uTTL, uType, uClass}); } -void DNSDistProtoBufMessage::serialize(std::string& data) const +void DNSDistProtoBufMessage::serialize(std::string& data, bool withOpenTelemetryTraceData) const { if ((data.capacity() - data.size()) < 128) { data.reserve(data.size() + 128); @@ -247,7 +247,9 @@ void DNSDistProtoBufMessage::serialize(std::string& data) const if (auto tracer = d_dq.ids.getTracer(); tracer != nullptr && d_dq.ids.tracingEnabled) { msg.setOpenTelemetryTraceID(tracer->getTraceID()); - msg.setOpenTelemetryData(tracer->getOTProtobuf()); + if (withOpenTelemetryTraceData) { + msg.setOpenTelemetryData(tracer->getOTProtobuf()); + } } } diff --git a/pdns/dnsdistdist/dnsdist-protobuf.hh b/pdns/dnsdistdist/dnsdist-protobuf.hh index 6824c716a3..9b1f56f595 100644 --- a/pdns/dnsdistdist/dnsdist-protobuf.hh +++ b/pdns/dnsdistdist/dnsdist-protobuf.hh @@ -61,7 +61,7 @@ public: void addMeta(const std::string& key, std::vector&& strValues, const std::vector& intValues); void addRR(DNSName&& qname, uint16_t uType, uint16_t uClass, uint32_t uTTL, const std::string& data); - void serialize(std::string& data) const; + void serialize(std::string& data, bool withOpenTelemetryTraceData = true) const; [[nodiscard]] std::string toDebugString() const; diff --git a/pdns/dnsdistdist/dnsdist.cc b/pdns/dnsdistdist/dnsdist.cc index 1640d4c1ed..b6b8aeaa63 100644 --- a/pdns/dnsdistdist/dnsdist.cc +++ b/pdns/dnsdistdist/dnsdist.cc @@ -651,20 +651,7 @@ bool sendUDPResponse(int origFD, const PacketBuffer& response, [[maybe_unused]] void handleResponseSent(const InternalQueryState& ids, double udiff, const ComboAddress& client, const ComboAddress& backend, unsigned int size, const dnsheader& cleartextDH, dnsdist::Protocol outgoingProtocol, bool fromBackend) { handleResponseSent(ids.qname, ids.qtype, udiff, client, backend, size, cleartextDH, outgoingProtocol, ids.protocol, fromBackend); - -#ifndef DISABLE_PROTOBUF - if (ids.tracingEnabled && !ids.delayedResponseMsgs.empty()) { - static thread_local std::string data; - for (auto const& msg_logger : ids.delayedResponseMsgs) { - data.clear(); - msg_logger.first->serialize(data); - if (!ids.d_rawProtobufContent.empty()) { - data.insert(data.end(), ids.d_rawProtobufContent.begin(), ids.d_rawProtobufContent.end()); - } - msg_logger.second->queueData(data); - } - } -#endif + ids.sendDelayedProtobufMessages(); } void handleResponseSent(const DNSName& qname, const QType& qtype, double udiff, const ComboAddress& client, const ComboAddress& backend, unsigned int size, const dnsheader& cleartextDH, dnsdist::Protocol outgoingProtocol, dnsdist::Protocol incomingProtocol, bool fromBackend)