]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
Use separate settings for tcp-fast-open (passive) and tcp-fast-open-connect (active)
authorOtto <otto.moerbeek@open-xchange.com>
Fri, 22 Jan 2021 11:34:03 +0000 (12:34 +0100)
committerOtto <otto.moerbeek@open-xchange.com>
Wed, 24 Mar 2021 10:14:23 +0000 (11:14 +0100)
Also warn if things cannot work due to kernel settings and go back to
async connect() now that OpenBSD handles that properly.

pdns/lwres.cc
pdns/pdns_recursor.cc
pdns/syncres.cc
pdns/syncres.hh

index 465699b47889bc35bc6d6884109652ca58b27006..1d981fede8677842e28d14c2c45fb665cb961deb 100644 (file)
@@ -327,14 +327,20 @@ LWResult::Result asyncresolve(const ComboAddress& ip, const DNSName& domain, int
       Socket s(ip.sin4.sin_family, SOCK_STREAM);
 
       s.setNonBlocking();
-      ComboAddress local = pdns::getQueryLocalAddress(ip.sin4.sin_family, 0);
-      if (SyncRes::s_tcp_fast_open > 0) {
-        s.setFastOpenConnect();
+      // v6 tcp does not seem to have fast open
+      if (ip.sin4.sin_family == AF_INET && SyncRes::s_tcp_fast_open_connect) {
+        try {
+          s.setFastOpenConnect();
+        }
+        catch (const NetworkError& e) {
+          g_log << Logger::Error << "tcp-fast-connect enabled but returned error: " << e.what() << endl;
+        }
       }
 
+      ComboAddress local = pdns::getQueryLocalAddress(ip.sin4.sin_family, 0);
       s.bind(local);
 
-      s.connect(ip, g_networkTimeoutMsec * 1000); // needed for fastopen EINPROGRESS and better anyway than the system wide connect timeout
+      s.connect(ip);
 
       uint16_t tlen=htons(vpacket.size());
       char *lenP=(char*)&tlen;
index 58546cd921184420dc6981ffbdf5a92515a7e024..921235a7330894f214d2eb781de1d654953a09b8 100644 (file)
@@ -3222,6 +3222,27 @@ static void handleNewUDPQuestion(int fd, FDMultiplexer::funcparam_t& var)
   }
 }
 
+static void checkFastOpenSysctl(bool active)
+{
+#ifdef __linux__
+  string line;
+  if (readFileIfThere("/proc/sys/net/ipv4/tcp_fastopen", &line)) {
+    int flag = std::stoi(line);
+    if (active && !(flag & 1)) {
+      g_log << Logger::Error << "tcp-fast-open-connect enabled but net.ipv4.tcp_fastopen does not allow it" << endl;
+    }
+    if (!active && !(flag & 2)) {
+      g_log << Logger::Error << "tcp-fast-open enabled but net.ipv4.tcp_fastopen does not allow it" << endl;
+    }
+  }
+  else {
+    g_log << Logger::Error << "Cannot determine if kernel setting allow fast-open" << endl;
+ }
+#else
+  g_log << Logger::Error << "Cannot determine if kernel setting allow fast-open" << endl;
+#endif
+}
+
 static void makeTCPServerSockets(deferredAdd_t& deferredAdds, std::set<int>& tcpSockets)
 {
   int fd;
@@ -3291,6 +3312,7 @@ static void makeTCPServerSockets(deferredAdd_t& deferredAdds, std::set<int>& tcp
     }
 
     if (SyncRes::s_tcp_fast_open > 0) {
+      checkFastOpenSysctl(false);
 #ifdef TCP_FASTOPEN
       if (setsockopt(fd, IPPROTO_TCP, TCP_FASTOPEN, &SyncRes::s_tcp_fast_open, sizeof SyncRes::s_tcp_fast_open) < 0) {
         int err = errno;
@@ -4670,8 +4692,13 @@ static int serviceMain(int argc, char*argv[])
   SyncRes::s_maxdepth=::arg().asNum("max-recursion-depth");
   SyncRes::s_rootNXTrust = ::arg().mustDo( "root-nx-trust");
   SyncRes::s_refresh_ttlperc = ::arg().asNum("refresh-on-ttl-perc");
-  SyncRes::s_tcp_fast_open = ::arg().asNum("tcp-fast-open");
   RecursorPacketCache::s_refresh_ttlperc = SyncRes::s_refresh_ttlperc;
+  SyncRes::s_tcp_fast_open = ::arg().asNum("tcp-fast-open");
+  SyncRes::s_tcp_fast_open_connect = ::arg().mustDo("tcp-fast-open-connect");
+
+  if (SyncRes::s_tcp_fast_open_connect) {
+    checkFastOpenSysctl(true);
+  }
 
   if(SyncRes::s_serverID.empty()) {
     SyncRes::s_serverID = myHostname;
@@ -5554,6 +5581,7 @@ int main(int argc, char **argv)
     ::arg().set("stats-snmp-disabled-list", "List of statistics that are prevented from being exported via SNMP")=defaultBlacklistedStats;
 
     ::arg().set("tcp-fast-open", "Enable TCP Fast Open support on the listening sockets, using the supplied numerical value as the queue size")="0";
+    ::arg().set("tcp-fast-open-connect", "Enable TCP Fast Open support on outgoing sockets")="no";
     ::arg().set("nsec3-max-iterations", "Maximum number of iterations allowed for an NSEC3 record")="2500";
 
     ::arg().set("cpu-map", "Thread to CPU mapping, space separated thread-id=cpu1,cpu2..cpuN pairs")="";
index 08619eed24845d8153ed8baec8bd5283c8f44f92..6170cdac1ffbd80eb2c40f04cad75c4cddf7e280 100644 (file)
@@ -99,6 +99,7 @@ bool SyncRes::s_qnameminimization;
 SyncRes::HardenNXD SyncRes::s_hardenNXD;
 unsigned int SyncRes::s_refresh_ttlperc;
 int SyncRes::s_tcp_fast_open;
+bool SyncRes::s_tcp_fast_open_connect;
 
 #define LOG(x) if(d_lm == Log) { g_log <<Logger::Warning << x; } else if(d_lm == Store) { d_trace << x; }
 
index 74c1a8f7449873ff599bfeecc4bff8aa7e0fd3a8..1afc73c5675f596d86849f353c13e5b6796b451d 100644 (file)
@@ -792,6 +792,7 @@ public:
   static HardenNXD s_hardenNXD;
   static unsigned int s_refresh_ttlperc;
   static int s_tcp_fast_open;
+  static bool s_tcp_fast_open_connect;
 
   std::unordered_map<std::string,bool> d_discardedPolicies;
   DNSFilterEngine::Policy d_appliedPolicy;