]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
dnsdist: Rename topRule() and friends
authorRemi Gacogne <remi.gacogne@powerdns.com>
Fri, 25 Sep 2020 14:32:22 +0000 (16:32 +0200)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Fri, 25 Sep 2020 14:32:22 +0000 (16:32 +0200)
pdns/dnsdist-console.cc
pdns/dnsdist-lua-rules.cc
pdns/dnsdistdist/docs/reference/config.rst
pdns/dnsdistdist/docs/rules-actions.rst

index efabac278874a195d90f13af8ac04f2244c01a10..f7980ad227fadabf2f4a3d7be30725b4bff5fc1d 100644 (file)
@@ -409,6 +409,10 @@ const std::vector<ConsoleKeyword> g_consoleKeywords{
   { "getServer", true, "id", "returns server with index 'n' or whose uuid matches if 'id' is an UUID string" },
   { "getServers", true, "", "returns a table with all defined servers" },
   { "getStatisticsCounters", true, "", "returns a map of statistic counters" },
+  { "getTopCacheHitResponseRules", true, "[top]", "return the `top` cache-hit response rules" },
+  { "getTopResponseRules", true, "[top]", "return the `top` response rules" },
+  { "getTopRules", true, "[top]", "return the `top` rules" },
+  { "getTopSelfAnsweredResponseRules", true, "[top]", "return the `top` self-answered response rules" },
   { "getTLSContext", true, "n", "returns the TLS context with index n" },
   { "getTLSFrontend", true, "n", "returns the TLS frontend with index n" },
   { "getTLSFrontendCount", true, "", "returns the number of DoT listeners" },
@@ -441,9 +445,13 @@ const std::vector<ConsoleKeyword> g_consoleKeywords{
   { "MaxQPSIPRule", true, "qps, [v4Mask=32 [, v6Mask=64 [, burst=qps [, expiration=300 [, cleanupDelay=60]]]]]", "matches traffic exceeding the qps limit per subnet" },
   { "MaxQPSRule", true, "qps", "matches traffic **not** exceeding this qps limit" },
   { "mvCacheHitResponseRule", true, "from, to", "move cache hit response rule 'from' to a position where it is in front of 'to'. 'to' can be one larger than the largest rule" },
+  { "mvCacheHitResponseRuleToTop", true, "", "move the last cache hit response rule to the first position" },
   { "mvResponseRule", true, "from, to", "move response rule 'from' to a position where it is in front of 'to'. 'to' can be one larger than the largest rule" },
+  { "mvResponseRuleToTop", true, "", "move the last response rule to the first position" },
   { "mvRule", true, "from, to", "move rule 'from' to a position where it is in front of 'to'. 'to' can be one larger than the largest rule, in which case the rule will be moved to the last position" },
+  { "mvRuleToTop", true, "", "move the last rule to the first position" },
   { "mvSelfAnsweredResponseRule", true, "from, to", "move self-answered response rule 'from' to a position where it is in front of 'to'. 'to' can be one larger than the largest rule" },
+  { "mvSelfAnsweredResponseRuleToTop", true, "", "move the last self-answered response rule to the first position" },
   { "NetmaskGroupRule", true, "nmg[, src]", "Matches traffic from/to the network range specified in nmg. Set the src parameter to false to match nmg against destination address instead of source address. This can be used to differentiate between clients" },
   { "newBPFFilter", true, "maxV4, maxV6, maxQNames", "Return a new eBPF socket filter with a maximum of maxV4 IPv4, maxV6 IPv6 and maxQNames qname entries in the block table" },
   { "newCA", true, "address", "Returns a ComboAddress based on `address`" },
@@ -600,13 +608,13 @@ const std::vector<ConsoleKeyword> g_consoleKeywords{
   { "testCrypto", true, "", "test of the crypto all works" },
   { "TimedIPSetRule", true, "", "Create a rule which matches a set of IP addresses which expire"}, 
   { "topBandwidth", true, "top", "show top-`top` clients that consume the most bandwidth over length of ringbuffer" },
-  { "topCacheHitResponseRule", true, "", "move the last cache hit response rule to the first position" },
+  { "topCacheHitResponseRules", true, "[top][, vars]", "show `top` cache-hit response rules" },
   { "topClients", true, "n", "show top-`n` clients sending the most queries over length of ringbuffer" },
   { "topQueries", true, "n[, labels]", "show top 'n' queries, as grouped when optionally cut down to 'labels' labels" },
   { "topResponses", true, "n, kind[, labels]", "show top 'n' responses with RCODE=kind (0=NO Error, 2=ServFail, 3=NXDomain), as grouped when optionally cut down to 'labels' labels" },
-  { "topResponseRule", true, "", "move the last response rule to the first position" },
-  { "topRule", true, "", "move the last rule to the first position" },
-  { "topSelfAnsweredResponseRule", true, "", "move the last self-answered response rule to the first position" },
+  { "topResponseRules", true, "[top][, vars]", "show `top` response rules" },
+  { "topRules", true, "[top][, vars]", "show `top` rules" },
+  { "topSelfAnsweredResponseRules", true, "[top][, vars]", "show `top` self-answered response rules" },
   { "topSlow", true, "[top][, limit][, labels]", "show `top` queries slower than `limit` milliseconds, grouped by last `labels` labels" },
   { "TrailingDataRule", true, "", "Matches if the query has trailing data" },
   { "truncateTC", true, "bool", "if set (defaults to no starting with dnsdist 1.2.0) truncate TC=1 answers so they are actually empty. Fixes an issue for PowerDNS Authoritative Server 2.9.22. Note: turning this on breaks compatibility with RFC 6891." },
index 4307b0d1315fb56b566b46c21d2ee4a17ba9d453..54b65e770b6e6280b23749347786f644ac27ffb0 100644 (file)
@@ -86,11 +86,12 @@ void parseRuleParams(boost::optional<luaruleparams_t> params, boost::uuids::uuid
 typedef std::unordered_map<std::string, boost::variant<bool, int, std::string, std::vector<std::pair<int,int> > > > ruleparams_t;
 
 template<typename T>
-static void showRules(GlobalStateHolder<vector<T> > *someRulActions, boost::optional<ruleparams_t> vars) {
-  setLuaNoSideEffect();
-  int num=0;
+static std::string rulesToString(const std::vector<T>& rules, boost::optional<ruleparams_t> vars)
+{
+  int num = 0;
   bool showUUIDs = false;
   size_t truncateRuleWidth = string::npos;
+  std::string result;
 
   if (vars) {
     if (vars->count("showUUIDs")) {
@@ -101,25 +102,33 @@ static void showRules(GlobalStateHolder<vector<T> > *someRulActions, boost::opti
     }
   }
 
-  auto rules = someRulActions->getLocal();
   if (showUUIDs) {
     boost::format fmt("%-3d %-38s %9d %9d %-56s %s\n");
-    g_outputBuffer += (fmt % "#" % "UUID" % "Cr. Order" % "Matches" % "Rule" % "Action").str();
-    for(const auto& lim : *rules) {
+    result += (fmt % "#" % "UUID" % "Cr. Order" % "Matches" % "Rule" % "Action").str();
+    for(const auto& lim : rules) {
       string name = lim.d_rule->toString().substr(0, truncateRuleWidth);
-      g_outputBuffer += (fmt % num % boost::uuids::to_string(lim.d_id) % lim.d_creationOrder % lim.d_rule->d_matches % name % lim.d_action->toString()).str();
+      result += (fmt % num % boost::uuids::to_string(lim.d_id) % lim.d_creationOrder % lim.d_rule->d_matches % name % lim.d_action->toString()).str();
       ++num;
     }
   }
   else {
     boost::format fmt("%-3d %9d %-56s %s\n");
-    g_outputBuffer += (fmt % "#" % "Matches" % "Rule" % "Action").str();
-    for(const auto& lim : *rules) {
+    result += (fmt % "#" % "Matches" % "Rule" % "Action").str();
+    for(const auto& lim : rules) {
       string name = lim.d_rule->toString().substr(0, truncateRuleWidth);
-      g_outputBuffer += (fmt % num % lim.d_rule->d_matches % name % lim.d_action->toString()).str();
+      result += (fmt % num % lim.d_rule->d_matches % name % lim.d_action->toString()).str();
       ++num;
     }
   }
+  return result;
+}
+
+template<typename T>
+static void showRules(GlobalStateHolder<vector<T> > *someRulActions, boost::optional<ruleparams_t> vars) {
+  setLuaNoSideEffect();
+
+  auto rules = someRulActions->getLocal();
+  g_outputBuffer += rulesToString(*rules, vars);
 }
 
 template<typename T>
@@ -147,7 +156,7 @@ static void rmRule(GlobalStateHolder<vector<T> > *someRulActions, boost::variant
 }
 
 template<typename T>
-static void topRule(GlobalStateHolder<vector<T> > *someRulActions) {
+static void moveRuleToTop(GlobalStateHolder<vector<T> > *someRulActions) {
   setLuaSideEffect();
   auto rules = someRulActions->getCopy();
   if(rules.empty())
@@ -178,6 +187,38 @@ static void mvRule(GlobalStateHolder<vector<T> > *someRespRulActions, unsigned i
   someRespRulActions->setState(std::move(rules));
 }
 
+template<typename T>
+static std::vector<T> getTopRules(const std::vector<T>& rules, unsigned int top)
+{
+  std::vector<std::pair<size_t, size_t>> counts;
+  counts.reserve(rules.size());
+
+  size_t pos = 0;
+  for (const auto& rule : rules) {
+    counts.push_back({rule.d_rule->d_matches.load(), pos});
+    pos++;
+  }
+
+  sort(counts.begin(), counts.end(), [](const decltype(counts)::value_type& a,
+                                        const decltype(counts)::value_type& b) {
+    return b.first < a.first;
+  });
+
+  std::vector<T> results;
+  results.reserve(top);
+
+  size_t count = 0;
+  for (const auto& entry : counts) {
+    results.emplace_back(rules.at(entry.second));
+    ++count;
+    if (count == top) {
+      break;
+    }
+  }
+
+  return results;
+}
+
 void setupLuaRules(LuaContext& luaCtx)
 {
   luaCtx.writeFunction("makeRule", makeRule);
@@ -192,8 +233,8 @@ void setupLuaRules(LuaContext& luaCtx)
       rmRule(&g_resprulactions, id);
     });
 
-  luaCtx.writeFunction("topResponseRule", []() {
-      topRule(&g_resprulactions);
+  luaCtx.writeFunction("mvResponseRuleToTop", []() {
+      moveRuleToTop(&g_resprulactions);
     });
 
   luaCtx.writeFunction("mvResponseRule", [](unsigned int from, unsigned int to) {
@@ -208,8 +249,8 @@ void setupLuaRules(LuaContext& luaCtx)
       rmRule(&g_cachehitresprulactions, id);
     });
 
-  luaCtx.writeFunction("topCacheHitResponseRule", []() {
-      topRule(&g_cachehitresprulactions);
+  luaCtx.writeFunction("mvCacheHitResponseRuleToTop", []() {
+      moveRuleToTop(&g_cachehitresprulactions);
     });
 
   luaCtx.writeFunction("mvCacheHitResponseRule", [](unsigned int from, unsigned int to) {
@@ -224,8 +265,8 @@ void setupLuaRules(LuaContext& luaCtx)
       rmRule(&g_selfansweredresprulactions, id);
     });
 
-  luaCtx.writeFunction("topSelfAnsweredResponseRule", []() {
-      topRule(&g_selfansweredresprulactions);
+  luaCtx.writeFunction("mvSelfAnsweredResponseRuleToTop", []() {
+      moveRuleToTop(&g_selfansweredresprulactions);
     });
 
   luaCtx.writeFunction("mvSelfAnsweredResponseRule", [](unsigned int from, unsigned int to) {
@@ -236,8 +277,8 @@ void setupLuaRules(LuaContext& luaCtx)
       rmRule(&g_rulactions, id);
     });
 
-  luaCtx.writeFunction("topRule", []() {
-      topRule(&g_rulactions);
+  luaCtx.writeFunction("mvRuleToTop", []() {
+      moveRuleToTop(&g_rulactions);
     });
 
   luaCtx.writeFunction("mvRule", [](unsigned int from, unsigned int to) {
@@ -265,6 +306,54 @@ void setupLuaRules(LuaContext& luaCtx)
         });
     });
 
+  luaCtx.writeFunction("getTopRules", [](boost::optional<unsigned int> top) {
+    setLuaNoSideEffect();
+    auto rules = g_rulactions.getLocal();
+    return getTopRules(*rules, top.get_value_or(10));
+  });
+
+  luaCtx.writeFunction("topRules", [](boost::optional<unsigned int> top, boost::optional<ruleparams_t> vars) {
+    setLuaNoSideEffect();
+    auto rules = g_rulactions.getLocal();
+    return rulesToString(getTopRules(*rules, top.get_value_or(10)), vars);
+  });
+
+  luaCtx.writeFunction("getCacheHitResponseRules", [](boost::optional<unsigned int> top) {
+    setLuaNoSideEffect();
+    auto rules = g_cachehitresprulactions.getLocal();
+    return getTopRules(*rules, top.get_value_or(10));
+  });
+
+  luaCtx.writeFunction("topCacheHitRules", [](boost::optional<unsigned int> top, boost::optional<ruleparams_t> vars) {
+    setLuaNoSideEffect();
+    auto rules = g_cachehitresprulactions.getLocal();
+    return rulesToString(getTopRules(*rules, top.get_value_or(10)), vars);
+  });
+
+  luaCtx.writeFunction("getTopResponseRules", [](boost::optional<unsigned int> top) {
+    setLuaNoSideEffect();
+    auto rules = g_resprulactions.getLocal();
+    return getTopRules(*rules, top.get_value_or(10));
+  });
+
+  luaCtx.writeFunction("topResponseRules", [](boost::optional<unsigned int> top, boost::optional<ruleparams_t> vars) {
+    setLuaNoSideEffect();
+    auto rules = g_resprulactions.getLocal();
+    return rulesToString(getTopRules(*rules, top.get_value_or(10)), vars);
+  });
+
+  luaCtx.writeFunction("getTopSelfAnsweredResponseRules", [](boost::optional<unsigned int> top) {
+    setLuaNoSideEffect();
+    auto rules = g_selfansweredresprulactions.getLocal();
+    return getTopRules(*rules, top.get_value_or(10));
+  });
+
+  luaCtx.writeFunction("topSelfAnsweredResponseRules", [](boost::optional<unsigned int> top, boost::optional<ruleparams_t> vars) {
+    setLuaNoSideEffect();
+    auto rules = g_selfansweredresprulactions.getLocal();
+    return rulesToString(getTopRules(*rules, top.get_value_or(10)), vars);
+  });
+
   luaCtx.writeFunction("MaxQPSIPRule", [](unsigned int qps, boost::optional<int> ipv4trunc, boost::optional<int> ipv6trunc, boost::optional<int> burst, boost::optional<unsigned int> expiration, boost::optional<unsigned int> cleanupDelay, boost::optional<unsigned int> scanFraction) {
       return std::shared_ptr<DNSRule>(new MaxQPSIPRule(qps, burst.get_value_or(qps), ipv4trunc.get_value_or(32), ipv6trunc.get_value_or(64), expiration.get_value_or(300), cleanupDelay.get_value_or(60), scanFraction.get_value_or(10)));
     });
index 359c50877ec746ec3cbd6d9f8bed2aa1692b35d2..f8b44df759832aaa917e5357006498ca12057a4e 100644 (file)
@@ -864,6 +864,38 @@ Status, Statistics and More
 
   Return the number of TLSFrontend binds.
 
+.. function:: getTopCacheHitResponseRules([top])
+
+  .. versionadded:: 1.6.0
+
+  Return the `top` cache-hit response rules that matched the most.
+
+  :param int top: How many response rules to return.
+
+.. function:: getTopResponseRules([top])
+
+  .. versionadded:: 1.6.0
+
+  Return the `top` response rules that matched the most.
+
+  :param int top: How many response rules to return.
+
+.. function:: getTopRules([top])
+
+  .. versionadded:: 1.6.0
+
+  Return the `top` rules that matched the most.
+
+  :param int top: How many rules to return.
+
+.. function:: getTopSelfAnsweredRules([top])
+
+  .. versionadded:: 1.6.0
+
+  Return the `top` self-answered rules that matched the most.
+
+  :param int top: How many rules to return.
+
 .. function:: grepq(selector[, num])
               grepq(selectors[, num])
 
@@ -959,6 +991,19 @@ Status, Statistics and More
 
   :param int num: Number to show, defaults to 10.
 
+.. function:: topCacheHitResponseRules([top [, options]])
+
+  .. versionadded:: 1.6.0
+
+  This function shows the cache-hit response rules having matched the most.
+
+  :param int top: How many rules to show.
+  :param table options: A table with key: value pairs with display options.
+
+  Options:
+
+  * ``showUUIDs=false``: bool - Whether to display the UUIDs, defaults to false.
+
 .. function:: topClients([num])
 
   Print the top ``num`` clients sending the most queries over length of ringbuffer
@@ -982,6 +1027,45 @@ Status, Statistics and More
   :param int rcode: :ref:`Response code <DNSRCode>`, defaults to 0 (No Error)
   :param int label: Number of labels to cut down to
 
+.. function:: topResponseRules([top [, options]])
+
+  .. versionadded:: 1.6.0
+
+  This function shows the response rules having matched the most.
+
+  :param int top: How many rules to show.
+  :param table options: A table with key: value pairs with display options.
+
+  Options:
+
+  * ``showUUIDs=false``: bool - Whether to display the UUIDs, defaults to false.
+
+.. function:: topRules([top [, options]])
+
+  .. versionadded:: 1.6.0
+
+  This function shows the rules having matched the most.
+
+  :param int top: How many rules to show.
+  :param table options: A table with key: value pairs with display options.
+
+  Options:
+
+  * ``showUUIDs=false``: bool - Whether to display the UUIDs, defaults to false.
+
+.. function:: topSelfAnsweredResponseRules([top [, options]])
+
+  .. versionadded:: 1.6.0
+
+  This function shows the self-answered response rules having matched the most.
+
+  :param int top: How many rules to show.
+  :param table options: A table with key: value pairs with display options.
+
+  Options:
+
+  * ``showUUIDs=false``: bool - Whether to display the UUIDs, defaults to false.
+
 .. function:: topSlow([num[, limit[, labels]]])
 
   Print the ``num`` slowest queries that are slower than ``limit`` milliseconds.
index 2d5055c71ffeca28335177b6c16f593cce912a65..2239566ffef7d49c0f34b6a6b3eeed1bb4bad62e 100644 (file)
@@ -313,6 +313,12 @@ For Rules related to the incoming query:
   :param int from: Rule number to move
   :param int to: Location to more the Rule to
 
+.. function:: mvRuleToTop()
+
+  .. versionadded:: 1.6.0
+
+  This function moves the last rule to the first position. Before 1.6.0 this was handled by :func:`topRule`.
+
 .. function:: newRuleAction(rule, action[, options])
 
   .. versionchanged:: 1.3.0
@@ -350,7 +356,10 @@ For Rules related to the incoming query:
 
 .. function:: topRule()
 
-  Move the last rule to the first position.
+  .. versionchanged:: 1.6.0
+    Replaced by :func:`mvRuleToTop`
+
+  Before 1.6.0 this functions used to move the last rule to the first position, which is now handled by :func:`mvRuleToTop`.
 
 .. function:: rmRule(id)
 
@@ -386,6 +395,12 @@ For Rules related to responses:
   :param int from: Rule number to move
   :param int to: Location to more the Rule to
 
+.. function:: mvResponseRuleToTop()
+
+  .. versionadded:: 1.6.0
+
+  This function moves the last response rule to the first position. Before 1.6.0 this was handled by :func:`topResponseRule`.
+
 .. function:: rmResponseRule(id)
 
   .. versionchanged:: 1.3.0
@@ -411,7 +426,10 @@ For Rules related to responses:
 
 .. function:: topResponseRule()
 
-  Move the last response rule to the first position.
+  .. versionchanged:: 1.6.0
+    Replaced by :func:`mvResponseRuleToTop`
+
+  Before 1.6.0, this function used to move the last response rule to the first position, which is now handled by :func:`mvResponseRuleToTop`.
 
 Functions for manipulating Cache Hit Response Rules:
 
@@ -442,6 +460,12 @@ Functions for manipulating Cache Hit Response Rules:
   :param int from: Rule number to move
   :param int to: Location to more the Rule to
 
+.. function:: mvCacheHitResponseRuleToTop()
+
+  .. versionadded:: 1.6.0
+
+  This function moves the last cache hit response rule to the first position. Before 1.6.0 this was handled by :func:`topCacheHitResponseRule`.
+
 .. function:: rmCacheHitResponseRule(id)
 
   .. versionadded:: 1.2.0
@@ -471,7 +495,10 @@ Functions for manipulating Cache Hit Response Rules:
 
   .. versionadded:: 1.2.0
 
-  Move the last cache hit response rule to the first position.
+  .. versionchanged:: 1.6.0
+    Replaced by :func:`mvCacheHitResponseRuleToTop`
+
+  Before 1.6.0, this function used to move the last cache hit response rule to the first position, which is now handled by :func:`mvCacheHitResponseRuleToTop`.
 
 Functions for manipulating Self-Answered Response Rules:
 
@@ -494,6 +521,12 @@ Functions for manipulating Self-Answered Response Rules:
   :param int from: Rule number to move
   :param int to: Location to more the Rule to
 
+.. function:: mvSelfAnsweredResponseRuleToTop()
+
+  .. versionadded:: 1.6.0
+
+  This function moves the last self-answered response rule to the first position. Before 1.6.0 this was handled by :func:`topSelfAnsweredResponseRule`.
+
 .. function:: rmSelfAnsweredResponseRule(id)
 
   .. versionadded:: 1.3.0
@@ -519,6 +552,11 @@ Functions for manipulating Self-Answered Response Rules:
 
   .. versionadded:: 1.3.0
 
+  .. versionchanged:: 1.6.0
+    Replaced by :func:`mvSelfAnsweredResponseRuleToTop`
+
+  Before 1.6.0 this function used to move the last cache hit response rule to the first position, which is now handled by :func:`mvSelfAnsweredResponseRuleToTop`.
+
   Move the last self answered response rule to the first position.
 
 .. _RulesIntro: