Skip to content

Commit 7254e92

Browse files
author
leoparente
authored
local_thread cached data (#243)
* local_thread cached data * replace pair with struct * dnsLayer should exist * perform cached data logic only in Handler class * thread_local member class * Add lower case qname method on DnsResource * Add support to robin hood map to dns transactions
1 parent aa29a79 commit 7254e92

File tree

7 files changed

+38
-13
lines changed

7 files changed

+38
-13
lines changed

conanfile.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ spdlog/1.9.2
1616
uvw/2.10.0
1717
yaml-cpp/0.7.0
1818
libpcap/1.10.1
19+
robin-hood-hashing/3.11.5
1920

2021
[build_requires]
2122
corrade/2020.06

src/handlers/dns/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ target_include_directories(VisorHandlerDns
2323

2424
target_link_libraries(VisorHandlerDns
2525
PUBLIC
26+
${CONAN_LIBS_ROBIN-HOOD-HASHING}
2627
Visor::Input::Pcap
2728
Visor::Input::Dnstap
2829
Visor::Input::Mock

src/handlers/dns/DnsResource.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,20 @@ IDnsResource::IDnsResource(DnsLayer *dnsLayer, size_t offsetInLayer)
1919
{
2020
char decodedName[256];
2121
m_NameLength = decodeName((const char *)getRawData(), decodedName);
22-
if (m_NameLength > 0)
22+
if (m_NameLength > 0) {
2323
m_DecodedName = decodedName;
24+
m_DecodedNameLower = m_DecodedName;
25+
std::transform(m_DecodedNameLower.begin(), m_DecodedNameLower.end(), m_DecodedNameLower.begin(),
26+
[](unsigned char c) { return std::tolower(c); });
27+
}
2428
}
2529

2630
IDnsResource::IDnsResource(uint8_t *emptyRawData)
2731
: m_DnsLayer(NULL)
2832
, m_OffsetInLayer(0)
2933
, m_NextResource(NULL)
3034
, m_DecodedName("")
35+
, m_DecodedNameLower("")
3136
, m_NameLength(0)
3237
, m_ExternalRawData(emptyRawData)
3338
{
@@ -228,6 +233,9 @@ bool IDnsResource::setName(const std::string &newName)
228233
memcpy(getRawData(), encodedName, encodedNameLen);
229234
m_NameLength = encodedNameLen;
230235
m_DecodedName = newName;
236+
m_DecodedNameLower = m_DecodedName;
237+
std::transform(m_DecodedNameLower.begin(), m_DecodedNameLower.end(), m_DecodedNameLower.begin(),
238+
[](unsigned char c) { return std::tolower(c); });
231239

232240
return true;
233241
}

src/handlers/dns/DnsResource.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ class IDnsResource
3535
size_t m_OffsetInLayer;
3636
IDnsResource* m_NextResource;
3737
std::string m_DecodedName;
38+
std::string m_DecodedNameLower;
3839
size_t m_NameLength;
3940
uint8_t* m_ExternalRawData;
4041

@@ -83,6 +84,11 @@ class IDnsResource
8384
*/
8485
const std::string& getName() const { return m_DecodedName; }
8586

87+
/**
88+
* @return The name of this record in lower case
89+
*/
90+
const std::string& getNameLower() const { return m_DecodedNameLower; }
91+
8692
/**
8793
* @return The record name's offset in the packet
8894
*/

src/handlers/dns/DnsStreamHandler.cpp

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020

2121
namespace visor::handler::dns {
2222

23+
thread_local DnsStreamHandler::DnsCacheData DnsStreamHandler::_cached_dns_layer;
24+
2325
DnsStreamHandler::DnsStreamHandler(const std::string &name, InputStream *stream, const Configurable *window_config, StreamHandler *handler)
2426
: visor::StreamMetricsHandler<DnsMetricsManager>(name, window_config)
2527
{
@@ -161,9 +163,14 @@ void DnsStreamHandler::process_udp_packet_cb(pcpp::Packet &payload, PacketDirect
161163
metric_port = dst_port;
162164
}
163165
if (metric_port) {
164-
DnsLayer dnsLayer(udpLayer, &payload);
165-
if (!_filtering(dnsLayer, dir, l3, pcpp::UDP, metric_port, stamp)) {
166-
_metrics->process_dns_layer(dnsLayer, dir, l3, pcpp::UDP, flowkey, metric_port, _static_suffix_size, stamp);
166+
if (flowkey != _cached_dns_layer.flowKey || stamp.tv_sec != _cached_dns_layer.timestamp.tv_sec || stamp.tv_nsec != _cached_dns_layer.timestamp.tv_nsec) {
167+
_cached_dns_layer.flowKey = flowkey;
168+
_cached_dns_layer.timestamp = stamp;
169+
_cached_dns_layer.dnsLayer = std::make_unique<DnsLayer>(udpLayer, &payload);
170+
}
171+
auto dnsLayer = _cached_dns_layer.dnsLayer.get();
172+
if (!_filtering(*dnsLayer, dir, l3, pcpp::UDP, metric_port, stamp)) {
173+
_metrics->process_dns_layer(*dnsLayer, dir, l3, pcpp::UDP, flowkey, metric_port, _static_suffix_size, stamp);
167174
_static_suffix_size = 0;
168175
// signal for chained stream handlers, if we have any
169176
udp_signal(payload, dir, l3, flowkey, stamp);
@@ -317,10 +324,7 @@ bool DnsStreamHandler::_filtering(DnsLayer &payload, [[maybe_unused]] PacketDire
317324
if (!payload.parseResources(true) || payload.getFirstQuery() == nullptr) {
318325
goto will_filter;
319326
}
320-
// we need an all lower case version of this, we can't get away without making a copy
321-
std::string qname_ci{payload.getFirstQuery()->getName()};
322-
std::transform(qname_ci.begin(), qname_ci.end(), qname_ci.begin(),
323-
[](unsigned char c) { return std::tolower(c); });
327+
std::string_view qname_ci = payload.getFirstQuery()->getNameLower();
324328
for (const auto &fqn : _f_qnames) {
325329
// if it matched, we know we are not filtering
326330
if (endsWith(qname_ci, fqn)) {
@@ -604,9 +608,7 @@ void DnsMetricsBucket::process_dns_layer(bool deep, DnsLayer &payload, pcpp::Pro
604608
auto query = payload.getFirstQuery();
605609
if (query) {
606610

607-
auto name = query->getName();
608-
std::transform(name.begin(), name.end(), name.begin(),
609-
[](unsigned char c) { return std::tolower(c); });
611+
auto name = query->getNameLower();
610612

611613
if (group_enabled(group::DnsMetrics::Cardinality)) {
612614
_dns_qnameCard.update(name);

src/handlers/dns/DnsStreamHandler.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,13 @@ class DnsStreamHandler final : public visor::StreamMetricsHandler<DnsMetricsMana
241241
{
242242
static constexpr size_t DNSTAP_TYPE_SIZE = 15;
243243

244+
struct DnsCacheData {
245+
uint32_t flowKey = 0;
246+
timespec timestamp = timespec();
247+
std::unique_ptr<DnsLayer> dnsLayer;
248+
};
249+
static thread_local DnsCacheData _cached_dns_layer;
250+
244251
// the input stream sources we support (only one will be in use at a time)
245252
PcapInputStream *_pcap_stream{nullptr};
246253
MockInputStream *_mock_stream{nullptr};

src/handlers/dns/querypairmgr.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
#include <chrono>
88
#include <memory>
9-
#include <unordered_map>
9+
#include <robin_hood.h>
1010

1111
namespace visor::handler::dns {
1212

@@ -32,7 +32,7 @@ class QueryResponsePairMgr
3232
{
3333

3434
using DnsXactID = std::pair<uint32_t, uint16_t>;
35-
typedef std::unordered_map<DnsXactID, DnsTransaction, hash_pair> DnsXactMap;
35+
typedef robin_hood::unordered_map<DnsXactID, DnsTransaction, hash_pair> DnsXactMap;
3636

3737
unsigned int _ttl_secs;
3838
DnsXactMap _dns_transactions;

0 commit comments

Comments
 (0)