]> granicus.if.org Git - pdns/commitdiff
dnsdist: Fix unlimited retries when TCP Fast Open is enabled
authorRemi Gacogne <remi.gacogne@powerdns.com>
Mon, 15 Jul 2019 13:07:10 +0000 (15:07 +0200)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Mon, 15 Jul 2019 13:59:50 +0000 (15:59 +0200)
Using the same flag to indicate whether a connection was reused
after being pulled from the pool AND to know if the TFO flag should
be passed to sendmsg() led to an unlimited number of reconnection
attemps when TFO was enabled and the backend closed the connection
right after a write (sendmsg() succeeds then read() returns 0 right
away).

pdns/dnsdist-tcp.cc

index be50cd305bb86480a0dfa5a0b2e95e2d3422d321..90dbfaec5a2f35d83c4759516016d8396ae743ad 100644 (file)
@@ -107,7 +107,7 @@ static std::unique_ptr<Socket> setupTCPDownstream(shared_ptr<DownstreamState>& d
 class TCPConnectionToBackend
 {
 public:
-  TCPConnectionToBackend(std::shared_ptr<DownstreamState>& ds, uint16_t& downstreamFailures, const struct timeval& now): d_ds(ds), d_connectionStartTime(now)
+  TCPConnectionToBackend(std::shared_ptr<DownstreamState>& ds, uint16_t& downstreamFailures, const struct timeval& now): d_ds(ds), d_connectionStartTime(now), d_enableFastOpen(ds->tcpFastOpen)
   {
     d_socket = setupTCPDownstream(d_ds, downstreamFailures);
     ++d_ds->tcpCurrentConnections;
@@ -154,12 +154,23 @@ public:
     d_fresh = false;
   }
 
+  void disableFastOpen()
+  {
+    d_enableFastOpen = false;
+  }
+
+  bool isFastOpenEnabled()
+  {
+    return d_enableFastOpen;
+  }
+
 private:
   std::unique_ptr<Socket> d_socket{nullptr};
   std::shared_ptr<DownstreamState> d_ds{nullptr};
   struct timeval d_connectionStartTime;
   uint64_t d_queries{0};
   bool d_fresh{true};
+  bool d_enableFastOpen{false};
 };
 
 static thread_local map<ComboAddress, std::deque<std::unique_ptr<TCPConnectionToBackend>>> t_downstreamConnections;
@@ -912,7 +923,7 @@ static void handleDownstreamIO(std::shared_ptr<IncomingTCPConnectionState>& stat
     if (state->d_state == IncomingTCPConnectionState::State::sendingQueryToBackend) {
       int socketFlags = 0;
 #ifdef MSG_FASTOPEN
-      if (state->d_ds->tcpFastOpen && state->d_downstreamConnection->isFresh()) {
+      if (state->d_downstreamConnection->isFastOpenEnabled()) {
         socketFlags |= MSG_FASTOPEN;
       }
 #endif /* MSG_FASTOPEN */
@@ -935,7 +946,7 @@ static void handleDownstreamIO(std::shared_ptr<IncomingTCPConnectionState>& stat
         state->d_currentPos += sent;
         iostate = IOState::NeedWrite;
         /* disable fast open on partial write */
-        state->d_downstreamConnection->setReused();
+        state->d_downstreamConnection->disableFastOpen();
       }
     }