]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
dnsdist: Add more Lua FFI bindings for the ring entries
authorRemi Gacogne <remi.gacogne@powerdns.com>
Tue, 14 Nov 2023 12:22:22 +0000 (13:22 +0100)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Tue, 14 Nov 2023 14:50:43 +0000 (15:50 +0100)
pdns/dnsdist-rings.hh
pdns/dnsdistdist/dnsdist-lua-ffi-interface.h
pdns/dnsdistdist/dnsdist-lua-ffi.cc
pdns/dnsdistdist/test-dnsdist-lua-ffi.cc

index 6bd93afb7ddda3315f750c5b852501c590568144..755d76979771ea235d2a053595f17f7bcdd0115e 100644 (file)
@@ -58,7 +58,7 @@ struct Rings {
     struct timespec when;
     struct dnsheader dh;
     unsigned int usec;
-    unsigned int size;
+    uint16_t size;
     uint16_t qtype;
     // outgoing protocol
     dnsdist::Protocol protocol;
@@ -236,7 +236,7 @@ private:
 #endif
   }
 
-  void insertResponseLocked(boost::circular_buffer<Response>& ring, const struct timespec& when, const ComboAddress& requestor, const DNSName& name, uint16_t qtype, unsigned int usec, unsigned int size, const struct dnsheader& dh, const ComboAddress& backend, dnsdist::Protocol protocol)
+  void insertResponseLocked(boost::circular_buffer<Response>& ring, const struct timespec& when, const ComboAddress& requestor, const DNSName& name, uint16_t qtype, unsigned int usec, uint16_t size, const struct dnsheader& dh, const ComboAddress& backend, dnsdist::Protocol protocol)
   {
     if (!ring.full()) {
       d_nbResponseEntries++;
index a0ff3bf9fbb4f69fc98375f8d7a22fbde13aa549..e0c980e49efce9629b1f33af63abf2c3d8412f33 100644 (file)
@@ -193,11 +193,22 @@ size_t dnsdist_ffi_packetcache_get_address_list_by_domain(const char* poolName,
 typedef struct dnsdist_ffi_ring_entry_list_t dnsdist_ffi_ring_entry_list_t;
 
 bool dnsdist_ffi_ring_entry_is_response(const dnsdist_ffi_ring_entry_list_t* list, size_t idx) __attribute__ ((visibility ("default")));
+double dnsdist_ffi_ring_entry_get_age(const dnsdist_ffi_ring_entry_list_t* list, size_t idx) __attribute__ ((visibility ("default")));
 const char* dnsdist_ffi_ring_entry_get_name(const dnsdist_ffi_ring_entry_list_t* list, size_t idx) __attribute__ ((visibility ("default")));
 uint16_t dnsdist_ffi_ring_entry_get_type(const dnsdist_ffi_ring_entry_list_t* list, size_t idx) __attribute__ ((visibility ("default")));
 const char* dnsdist_ffi_ring_entry_get_requestor(const dnsdist_ffi_ring_entry_list_t* list, size_t idx) __attribute__ ((visibility ("default")));
+const char* dnsdist_ffi_ring_entry_get_backend(const dnsdist_ffi_ring_entry_list_t* list, size_t idx) __attribute__ ((visibility ("default")));
 uint8_t dnsdist_ffi_ring_entry_get_protocol(const dnsdist_ffi_ring_entry_list_t* list, size_t idx) __attribute__ ((visibility ("default")));
 uint16_t dnsdist_ffi_ring_entry_get_size(const dnsdist_ffi_ring_entry_list_t* list, size_t idx) __attribute__ ((visibility ("default")));
+uint16_t dnsdist_ffi_ring_entry_get_latency(const dnsdist_ffi_ring_entry_list_t* list, size_t idx) __attribute__ ((visibility ("default")));
+uint16_t dnsdist_ffi_ring_entry_get_id(const dnsdist_ffi_ring_entry_list_t* list, size_t idx) __attribute__ ((visibility ("default")));
+uint8_t dnsdist_ffi_ring_entry_get_rcode(const dnsdist_ffi_ring_entry_list_t* list, size_t idx) __attribute__ ((visibility ("default")));
+bool dnsdist_ffi_ring_entry_get_aa(const dnsdist_ffi_ring_entry_list_t* list, size_t idx) __attribute__ ((visibility ("default")));
+bool dnsdist_ffi_ring_entry_get_rd(const dnsdist_ffi_ring_entry_list_t* list, size_t idx) __attribute__ ((visibility ("default")));
+bool dnsdist_ffi_ring_entry_get_tc(const dnsdist_ffi_ring_entry_list_t* list, size_t idx) __attribute__ ((visibility ("default")));
+uint16_t dnsdist_ffi_ring_entry_get_ancount(const dnsdist_ffi_ring_entry_list_t* list, size_t idx) __attribute__ ((visibility ("default")));
+uint16_t dnsdist_ffi_ring_entry_get_nscount(const dnsdist_ffi_ring_entry_list_t* list, size_t idx) __attribute__ ((visibility ("default")));
+uint16_t dnsdist_ffi_ring_entry_get_arcount(const dnsdist_ffi_ring_entry_list_t* list, size_t idx) __attribute__ ((visibility ("default")));
 bool dnsdist_ffi_ring_entry_has_mac_address(const dnsdist_ffi_ring_entry_list_t* list, size_t idx) __attribute__ ((visibility ("default")));
 const char* dnsdist_ffi_ring_entry_get_mac_address(const dnsdist_ffi_ring_entry_list_t* list, size_t idx) __attribute__ ((visibility ("default")));
 
index 1ec5c037821a6e8e8ccf564031fbacd61fc7c3dc..7d1d831d170ee43e1ce54eeaeb64a9265f7fdf4c 100644 (file)
@@ -1224,7 +1224,11 @@ struct dnsdist_ffi_ring_entry_list_t
     std::string qname;
     std::string requestor;
     std::string macAddr;
-    size_t size;
+    std::string ds;
+    dnsheader dh;
+    double age;
+    unsigned int latency;
+    uint16_t size;
     uint16_t qtype;
     dnsdist::Protocol protocol;
     bool isResponse;
@@ -1242,6 +1246,15 @@ bool dnsdist_ffi_ring_entry_is_response(const dnsdist_ffi_ring_entry_list_t* lis
   return list->d_entries.at(idx).isResponse;
 }
 
+double dnsdist_ffi_ring_entry_get_age(const dnsdist_ffi_ring_entry_list_t* list, size_t idx)
+{
+  if (list == nullptr || idx >= list->d_entries.size()) {
+    return 0;
+  }
+
+  return list->d_entries.at(idx).age;
+}
+
 const char* dnsdist_ffi_ring_entry_get_name(const dnsdist_ffi_ring_entry_list_t* list, size_t idx)
 {
   if (list == nullptr || idx >= list->d_entries.size()) {
@@ -1258,7 +1271,6 @@ uint16_t dnsdist_ffi_ring_entry_get_type(const dnsdist_ffi_ring_entry_list_t* li
   }
 
   return list->d_entries.at(idx).qtype;
-
 }
 
 const char* dnsdist_ffi_ring_entry_get_requestor(const dnsdist_ffi_ring_entry_list_t* list, size_t idx)
@@ -1270,6 +1282,15 @@ const char* dnsdist_ffi_ring_entry_get_requestor(const dnsdist_ffi_ring_entry_li
   return list->d_entries.at(idx).requestor.c_str();
 }
 
+const char* dnsdist_ffi_ring_entry_get_backend(const dnsdist_ffi_ring_entry_list_t* list, size_t idx)
+{
+  if (list == nullptr || idx >= list->d_entries.size()) {
+    return nullptr;
+  }
+
+  return list->d_entries.at(idx).ds.c_str();
+}
+
 uint8_t dnsdist_ffi_ring_entry_get_protocol(const dnsdist_ffi_ring_entry_list_t* list, size_t idx)
 {
   if (list == nullptr || idx >= list->d_entries.size()) {
@@ -1286,7 +1307,87 @@ uint16_t dnsdist_ffi_ring_entry_get_size(const dnsdist_ffi_ring_entry_list_t* li
   }
 
   return list->d_entries.at(idx).size;
+}
+
+uint16_t dnsdist_ffi_ring_entry_get_latency(const dnsdist_ffi_ring_entry_list_t* list, size_t idx)
+{
+  if (list == nullptr || idx >= list->d_entries.size()) {
+    return 0;
+  }
+
+  return list->d_entries.at(idx).latency;
+}
+
+uint16_t dnsdist_ffi_ring_entry_get_id(const dnsdist_ffi_ring_entry_list_t* list, size_t idx)
+{
+  if (list == nullptr || idx >= list->d_entries.size()) {
+    return 0;
+  }
+
+  return ntohs(list->d_entries.at(idx).dh.id);
+}
+
+uint8_t dnsdist_ffi_ring_entry_get_rcode(const dnsdist_ffi_ring_entry_list_t* list, size_t idx)
+{
+  if (list == nullptr || idx >= list->d_entries.size()) {
+    return 0;
+  }
+
+  return list->d_entries.at(idx).dh.rcode;
+}
+
+bool dnsdist_ffi_ring_entry_get_aa(const dnsdist_ffi_ring_entry_list_t* list, size_t idx)
+{
+  if (list == nullptr || idx >= list->d_entries.size()) {
+    return 0;
+  }
+
+  return list->d_entries.at(idx).dh.aa;
+}
+
+bool dnsdist_ffi_ring_entry_get_rd(const dnsdist_ffi_ring_entry_list_t* list, size_t idx)
+{
+  if (list == nullptr || idx >= list->d_entries.size()) {
+    return 0;
+  }
 
+  return list->d_entries.at(idx).dh.rd;
+}
+
+bool dnsdist_ffi_ring_entry_get_tc(const dnsdist_ffi_ring_entry_list_t* list, size_t idx)
+{
+  if (list == nullptr || idx >= list->d_entries.size()) {
+    return 0;
+  }
+
+  return list->d_entries.at(idx).dh.tc;
+}
+
+uint16_t dnsdist_ffi_ring_entry_get_ancount(const dnsdist_ffi_ring_entry_list_t* list, size_t idx)
+{
+  if (list == nullptr || idx >= list->d_entries.size()) {
+    return 0;
+  }
+
+  return ntohs(list->d_entries.at(idx).dh.ancount);
+}
+
+uint16_t dnsdist_ffi_ring_entry_get_nscount(const dnsdist_ffi_ring_entry_list_t* list, size_t idx)
+{
+  if (list == nullptr || idx >= list->d_entries.size()) {
+    return 0;
+  }
+
+  return ntohs(list->d_entries.at(idx).dh.nscount);
+}
+
+uint16_t dnsdist_ffi_ring_entry_get_arcount(const dnsdist_ffi_ring_entry_list_t* list, size_t idx)
+{
+  if (list == nullptr || idx >= list->d_entries.size()) {
+    return 0;
+  }
+
+  return ntohs(list->d_entries.at(idx).dh.arcount);
 }
 
 bool dnsdist_ffi_ring_entry_has_mac_address(const dnsdist_ffi_ring_entry_list_t* list, size_t idx)
@@ -1305,7 +1406,6 @@ const char* dnsdist_ffi_ring_entry_get_mac_address(const dnsdist_ffi_ring_entry_
   }
 
   return list->d_entries.at(idx).macAddr.data();
-
 }
 
 void dnsdist_ffi_ring_entry_list_free(dnsdist_ffi_ring_entry_list_t* list)
@@ -1313,22 +1413,23 @@ void dnsdist_ffi_ring_entry_list_free(dnsdist_ffi_ring_entry_list_t* list)
   delete list;
 }
 
-template<typename T> static void addRingEntryToList(std::unique_ptr<dnsdist_ffi_ring_entry_list_t>& list, const T& entry)
+template<typename T> static void addRingEntryToList(std::unique_ptr<dnsdist_ffi_ring_entry_list_t>& list, const struct timespec& now, const T& entry)
 {
+  auto age = DiffTime(entry.when, now);
+
   constexpr bool response = std::is_same_v<T, Rings::Response>;
-#if defined(DNSDIST_RINGS_WITH_MACADDRESS)
   if constexpr (!response) {
-    dnsdist_ffi_ring_entry_list_t::entry tmp{entry.name.toString(), entry.requestor.toStringWithPort(), entry.hasmac ? std::string(reinterpret_cast<const char*>(entry.macaddress.data()), entry.macaddress.size()) : std::string(), entry.size, entry.qtype, entry.protocol, response};
+#if defined(DNSDIST_RINGS_WITH_MACADDRESS)
+    dnsdist_ffi_ring_entry_list_t::entry tmp{entry.name.toString(), entry.requestor.toStringWithPort(), entry.hasmac ? std::string(reinterpret_cast<const char*>(entry.macaddress.data()), entry.macaddress.size()) : std::string(), std::string(), entry.dh, age, 0, entry.size, entry.qtype, entry.protocol, response};
+#else
+    dnsdist_ffi_ring_entry_list_t::entry tmp{entry.name.toString(), entry.requestor.toStringWithPort(), std::string(), std::string(), entry.dh, age, 0, entry.size, entry.qtype, entry.protocol, response};
+#endif
     list->d_entries.push_back(std::move(tmp));
   }
   else {
-    dnsdist_ffi_ring_entry_list_t::entry tmp{entry.name.toString(), entry.requestor.toStringWithPort(), std::string(), entry.size, entry.qtype, entry.protocol, response};
+    dnsdist_ffi_ring_entry_list_t::entry tmp{entry.name.toString(), entry.requestor.toStringWithPort(), std::string(), entry.ds.toStringWithPort(), entry.dh, age, entry.usec, entry.size, entry.qtype, entry.protocol, response};
     list->d_entries.push_back(std::move(tmp));
   }
-#else
-  dnsdist_ffi_ring_entry_list_t::entry tmp{entry.name.toString(), entry.requestor.toStringWithPort(), std::string(), entry.size, entry.qtype, entry.protocol, response};
-  list->d_entries.push_back(std::move(tmp));
-#endif
 }
 
 size_t dnsdist_ffi_ring_get_entries(dnsdist_ffi_ring_entry_list_t** out)
@@ -1337,18 +1438,22 @@ size_t dnsdist_ffi_ring_get_entries(dnsdist_ffi_ring_entry_list_t** out)
     return 0;
   }
   auto list = std::make_unique<dnsdist_ffi_ring_entry_list_t>();
+  struct timespec now
+  {
+  };
+  gettime(&now);
 
   for (const auto& shard : g_rings.d_shards) {
     {
       auto ql = shard->queryRing.lock();
       for (const auto& entry : *ql) {
-        addRingEntryToList(list, entry);
+        addRingEntryToList(list, now, entry);
       }
     }
     {
       auto rl = shard->respRing.lock();
       for (const auto& entry : *rl) {
-        addRingEntryToList(list, entry);
+        addRingEntryToList(list, now, entry);
       }
     }
   }
@@ -1379,6 +1484,10 @@ size_t dnsdist_ffi_ring_get_entries_by_addr(const char* addr, dnsdist_ffi_ring_e
   }
 
   auto list = std::make_unique<dnsdist_ffi_ring_entry_list_t>();
+  struct timespec now
+  {
+  };
+  gettime(&now);
 
   auto compare = ComboAddress::addressOnlyEqual();
   for (const auto& shard : g_rings.d_shards) {
@@ -1389,7 +1498,7 @@ size_t dnsdist_ffi_ring_get_entries_by_addr(const char* addr, dnsdist_ffi_ring_e
           continue;
         }
 
-        addRingEntryToList(list, entry);
+        addRingEntryToList(list, now, entry);
       }
     }
     {
@@ -1399,7 +1508,7 @@ size_t dnsdist_ffi_ring_get_entries_by_addr(const char* addr, dnsdist_ffi_ring_e
           continue;
         }
 
-        addRingEntryToList(list, entry);
+        addRingEntryToList(list, now, entry);
       }
     }
   }
@@ -1421,6 +1530,10 @@ size_t dnsdist_ffi_ring_get_entries_by_mac(const char* addr, dnsdist_ffi_ring_en
   return 0;
 #else
   auto list = std::make_unique<dnsdist_ffi_ring_entry_list_t>();
+  struct timespec now
+  {
+  };
+  gettime(&now);
 
   for (const auto& shard : g_rings.d_shards) {
     auto ql = shard->queryRing.lock();
@@ -1429,7 +1542,7 @@ size_t dnsdist_ffi_ring_get_entries_by_mac(const char* addr, dnsdist_ffi_ring_en
         continue;
       }
 
-      addRingEntryToList(list, entry);
+      addRingEntryToList(list, now, entry);
     }
   }
 
index 56047a7f0c8e79ae4c5da787f34d42cf3a8b1b0f..72b3d383087e60cd2bb038f3394033eca72667f4 100644 (file)
@@ -684,6 +684,12 @@ BOOST_AUTO_TEST_CASE(test_RingBuffers)
 {
   dnsheader dh;
   memset(&dh, 0, sizeof(dh));
+  dh.id = htons(42);
+  dh.rd = 1;
+  dh.ancount = htons(1);
+  dh.nscount = htons(1);
+  dh.arcount = htons(1);
+  dh.rcode = RCode::NXDomain;
   DNSName qname("rings.luaffi.powerdns.com.");
   ComboAddress requestor1("192.0.2.1");
   ComboAddress backend("192.0.2.42");
@@ -716,11 +722,22 @@ BOOST_AUTO_TEST_CASE(test_RingBuffers)
     BOOST_CHECK_EQUAL(dnsdist_ffi_ring_get_entries_by_mac(nullptr, nullptr), 0U);
     BOOST_CHECK(list == nullptr);
     BOOST_CHECK(!dnsdist_ffi_ring_entry_is_response(nullptr, 0));
+    BOOST_CHECK(dnsdist_ffi_ring_entry_get_age(nullptr, 0) == 0.0);
     BOOST_CHECK(dnsdist_ffi_ring_entry_get_name(nullptr, 0) == nullptr);
     BOOST_CHECK(dnsdist_ffi_ring_entry_get_type(nullptr, 0) == 0);
     BOOST_CHECK(dnsdist_ffi_ring_entry_get_requestor(nullptr, 0) == nullptr);
+    BOOST_CHECK(dnsdist_ffi_ring_entry_get_backend(nullptr, 0) == nullptr);
     BOOST_CHECK(dnsdist_ffi_ring_entry_get_protocol(nullptr, 0) == 0);
     BOOST_CHECK(dnsdist_ffi_ring_entry_get_size(nullptr, 0) == 0);
+    BOOST_CHECK(dnsdist_ffi_ring_entry_get_latency(nullptr, 0) == 0);
+    BOOST_CHECK(dnsdist_ffi_ring_entry_get_id(nullptr, 0) == 0);
+    BOOST_CHECK(dnsdist_ffi_ring_entry_get_rcode(nullptr, 0) == 0);
+    BOOST_CHECK(dnsdist_ffi_ring_entry_get_aa(nullptr, 0) == false);
+    BOOST_CHECK(dnsdist_ffi_ring_entry_get_rd(nullptr, 0) == false);
+    BOOST_CHECK(dnsdist_ffi_ring_entry_get_tc(nullptr, 0) == false);
+    BOOST_CHECK(dnsdist_ffi_ring_entry_get_ancount(nullptr, 0) == 0);
+    BOOST_CHECK(dnsdist_ffi_ring_entry_get_nscount(nullptr, 0) == 0);
+    BOOST_CHECK(dnsdist_ffi_ring_entry_get_arcount(nullptr, 0) == 0);
     BOOST_CHECK(!dnsdist_ffi_ring_entry_has_mac_address(nullptr, 0));
     BOOST_CHECK(dnsdist_ffi_ring_entry_get_mac_address(nullptr, 0) == nullptr);
   }
@@ -732,11 +749,25 @@ BOOST_AUTO_TEST_CASE(test_RingBuffers)
   BOOST_CHECK(dnsdist_ffi_ring_entry_is_response(list, 1));
 
   for (size_t idx = 0; idx < 2; idx++) {
+    BOOST_CHECK(dnsdist_ffi_ring_entry_get_age(list, idx) >= 0.0);
+    BOOST_CHECK(dnsdist_ffi_ring_entry_get_age(list, idx) < 2.0);
     BOOST_CHECK(dnsdist_ffi_ring_entry_get_name(list, idx) == qname.toString());
     BOOST_CHECK(dnsdist_ffi_ring_entry_get_type(list, idx) == qtype);
     BOOST_CHECK(dnsdist_ffi_ring_entry_get_requestor(list, idx) == requestor1.toStringWithPort());
     BOOST_CHECK(dnsdist_ffi_ring_entry_get_protocol(list, idx) == protocol.toNumber());
     BOOST_CHECK_EQUAL(dnsdist_ffi_ring_entry_get_size(list, idx), size);
+    BOOST_CHECK_EQUAL(dnsdist_ffi_ring_entry_get_id(list, idx), 42U);
+    BOOST_CHECK(dnsdist_ffi_ring_entry_get_aa(list, idx) == false);
+    BOOST_CHECK(dnsdist_ffi_ring_entry_get_rd(list, idx) == true);
+    BOOST_CHECK(dnsdist_ffi_ring_entry_get_tc(list, idx) == false);
+    BOOST_CHECK(dnsdist_ffi_ring_entry_get_ancount(list, idx) == 1);
+    BOOST_CHECK(dnsdist_ffi_ring_entry_get_nscount(list, idx) == 1);
+    BOOST_CHECK(dnsdist_ffi_ring_entry_get_arcount(list, idx) == 1);
+    BOOST_CHECK(dnsdist_ffi_ring_entry_get_rcode(list, idx) == RCode::NXDomain);
+    if (dnsdist_ffi_ring_entry_is_response(list, idx)) {
+      BOOST_CHECK(dnsdist_ffi_ring_entry_get_backend(list, idx) == backend.toStringWithPort());
+      BOOST_CHECK_EQUAL(dnsdist_ffi_ring_entry_get_latency(list, idx), responseTime);
+    }
     BOOST_CHECK(!dnsdist_ffi_ring_entry_has_mac_address(list, idx));
     BOOST_CHECK(dnsdist_ffi_ring_entry_get_mac_address(list, idx) == std::string());
   }
@@ -744,7 +775,7 @@ BOOST_AUTO_TEST_CASE(test_RingBuffers)
   dnsdist_ffi_ring_entry_list_free(list);
   list = nullptr;
 
-  // no the right requestor
+  // not the right requestor
   BOOST_REQUIRE_EQUAL(dnsdist_ffi_ring_get_entries_by_addr("192.0.2.2", &list), 0U);
   BOOST_CHECK(list == nullptr);