From b786099754847660157fa3e4128b523bb666bd2b Mon Sep 17 00:00:00 2001 From: bert hubert Date: Sun, 13 Dec 2015 21:19:36 +0100 Subject: [PATCH] add benchRule which benchmarks rules and AndRule which Ands rules together --- pdns/README-dnsdist.md | 3 +++ pdns/dnsdist-lua.cc | 56 ++++++++++++++++++++++++++++++++++++++++++ pdns/dnsrulactions.hh | 35 ++++++++++++++++++++++++++ 3 files changed, 94 insertions(+) diff --git a/pdns/README-dnsdist.md b/pdns/README-dnsdist.md index 76e69c7ea..ba2f2c7bc 100644 --- a/pdns/README-dnsdist.md +++ b/pdns/README-dnsdist.md @@ -243,9 +243,12 @@ Rules have selectors and actions. Current selectors are: * Query domain * QPS Limit total * QPS Limit per IP address or subnet + * QType (QTypeRule) * RegexRule on query name * Packet requests DNSSEC processing +A special rule is `AndRule{rule1, rule2}`, which only matches if all of its subrules match. + Current actions are: * Drop * Route to a pool diff --git a/pdns/dnsdist-lua.cc b/pdns/dnsdist-lua.cc index 5e78e8132..6f2c18b02 100644 --- a/pdns/dnsdist-lua.cc +++ b/pdns/dnsdist-lua.cc @@ -5,6 +5,7 @@ #include "sodcrypto.hh" #include "base64.hh" #include +#include "dnswriter.hh" #include "lock.hh" using std::thread; @@ -477,6 +478,61 @@ vector> setupLua(bool client, const std::string& confi return std::shared_ptr(new RegexRule(str)); }); + + g_lua.writeFunction("benchRule", [](std::shared_ptr rule, boost::optional times_, boost::optional suffix_) { + int times = times_.get_value_or(100000); + DNSName suffix(suffix_.get_value_or("powerdns.com")); + struct item { + vector packet; + ComboAddress rem; + DNSName qname; + uint16_t qtype; + }; + vector items; + items.reserve(1000); + for(int n=0; n < 1000; ++n) { + struct item i; + i.qname=DNSName(std::to_string(random())); + i.qname += suffix; + i.qtype = random() % 0xff; + i.rem=ComboAddress("127.0.0.1"); + i.rem.sin4.sin_addr.s_addr = random(); + DNSPacketWriter pw(i.packet, i.qname, i.qtype); + items.push_back(i); + } + + int matches=0; + DTime dt; + dt.set(); + for(int n=0; n < times; ++n) { + const item& i = items[n % items.size()]; + struct dnsheader* dh = (struct dnsheader*)&i.packet[0]; + if(rule->matches(i.rem, i.qname, i.qtype, dh, i.packet.size())) + matches++; + } + double udiff=dt.udiff(); + g_outputBuffer=(boost::format("Had %d matches out of %d, %.1f qps, in %.1f usec\n") % matches % times % (1000000*(1.0*times/udiff)) % udiff).str(); + + }); + g_lua.writeFunction("QTypeRule", [](boost::variant str) { + uint16_t qtype; + if(auto dir = boost::get(&str)) { + qtype = *dir; + } + else { + string val=boost::get(str); + qtype = QType::chartocode(val.c_str()); + if(!qtype) + throw std::runtime_error("Unable to convert '"+val+"' to a DNS type"); + } + return std::shared_ptr(new QTypeRule(qtype)); + }); + + g_lua.writeFunction("AndRule", [](vector > >a) { + return std::shared_ptr(new AndRule(a)); + }); + + g_lua.writeFunction("addAction", [](luadnsrule_t var, std::shared_ptr ea) { auto rule=makeRule(var); diff --git a/pdns/dnsrulactions.hh b/pdns/dnsrulactions.hh index b5d7ad5d7..451a313f2 100644 --- a/pdns/dnsrulactions.hh +++ b/pdns/dnsrulactions.hh @@ -99,6 +99,41 @@ public: } }; +class AndRule : public DNSRule +{ +public: + AndRule(const vector > >& rules) + { + for(const auto& r : rules) + d_rules.push_back(r.second); + } + + bool matches(const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh, int len) const override + { + auto iter = d_rules.begin(); + for(; iter != d_rules.end(); ++iter) + if(!(*iter)->matches(remote, qname, qtype, dh, len)) + break; + return iter == d_rules.end(); + } + + string toString() const override + { + string ret; + for(const auto& rule : d_rules) { + if(!ret.empty()) + ret+= " && "; + ret += "("+ rule->toString()+")"; + } + return ret; + } +private: + + vector > d_rules; + +}; + + class RegexRule : public DNSRule { public: -- 2.40.0