]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
add benchRule which benchmarks rules and AndRule which Ands rules together
authorbert hubert <bert.hubert@netherlabs.nl>
Sun, 13 Dec 2015 20:19:36 +0000 (21:19 +0100)
committerbert hubert <bert.hubert@netherlabs.nl>
Sun, 13 Dec 2015 20:19:36 +0000 (21:19 +0100)
pdns/README-dnsdist.md
pdns/dnsdist-lua.cc
pdns/dnsrulactions.hh

index 76e69c7eadab87258ed07c0a32a7e7de746983dc..ba2f2c7bc615c9353e931a20856a5c62fcb9eceb 100644 (file)
@@ -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
index 5e78e8132364511e3b35417cd7ee3a97844948fc..6f2c18b0233934d3ddb9eac134588f24b496bc2b 100644 (file)
@@ -5,6 +5,7 @@
 #include "sodcrypto.hh"
 #include "base64.hh"
 #include <fstream>
+#include "dnswriter.hh"
 #include "lock.hh"
 
 using std::thread;
@@ -477,6 +478,61 @@ vector<std::function<void(void)>> setupLua(bool client, const std::string& confi
       return std::shared_ptr<DNSRule>(new RegexRule(str));
     });
 
+
+  g_lua.writeFunction("benchRule", [](std::shared_ptr<DNSRule> rule, boost::optional<int> times_, boost::optional<string> suffix_)  {
+      int times = times_.get_value_or(100000);
+      DNSName suffix(suffix_.get_value_or("powerdns.com"));
+      struct item {
+        vector<uint8_t> packet;        
+        ComboAddress rem;
+        DNSName qname;
+        uint16_t qtype;
+      };
+      vector<item> 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<int, std::string> str) {
+      uint16_t qtype;
+      if(auto dir = boost::get<int>(&str)) {
+        qtype = *dir;
+      }
+      else {
+        string val=boost::get<string>(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<DNSRule>(new QTypeRule(qtype));
+    });
+
+  g_lua.writeFunction("AndRule", [](vector<pair<int, std::shared_ptr<DNSRule> > >a) {
+      return std::shared_ptr<DNSRule>(new AndRule(a));
+    });
+
+
   g_lua.writeFunction("addAction", [](luadnsrule_t var, std::shared_ptr<DNSAction> ea) 
                      {
                        auto rule=makeRule(var);
index b5d7ad5d7b5350e7c257eeb2e7ebf9c90170f5c8..451a313f25e57920fc01277287b64cd5a1be4755 100644 (file)
@@ -99,6 +99,41 @@ public:
   }
 };
 
+class AndRule : public DNSRule
+{
+public:
+  AndRule(const vector<pair<int, shared_ptr<DNSRule> > >& 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<std::shared_ptr<DNSRule> > d_rules;
+
+};
+
+
 class RegexRule : public DNSRule
 {
 public: