You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by zw...@apache.org on 2020/07/13 22:56:30 UTC

[trafficserver] 01/02: Open UDP ports on traffic_manager if ports are configured for QUIC (#6808)

This is an automated email from the ASF dual-hosted git repository.

zwoop pushed a commit to branch 9.0.x
in repository https://gitbox.apache.org/repos/asf/trafficserver.git

commit 9f89bc116608eb6972c75b29023afdd7c19147fc
Author: Masakazu Kitajo <ma...@apache.org>
AuthorDate: Tue Jul 14 07:49:08 2020 +0900

    Open UDP ports on traffic_manager if ports are configured for QUIC (#6808)
    
    (cherry picked from commit f1ef5ee6d977c80f0a5c5b6b7badcaba4f5833c8)
---
 iocore/net/I_UDPNet.h              |  3 +-
 iocore/net/QUICNetProcessor.cc     |  2 +-
 iocore/net/UnixUDPNet.cc           | 19 +++++----
 iocore/net/test_I_UDPNet.cc        |  2 +-
 mgmt/LocalManager.cc               | 80 +++++++++++++++++++++++++++++++++-----
 mgmt/LocalManager.h                |  3 +-
 src/traffic_server/InkIOCoreAPI.cc |  2 +-
 7 files changed, 90 insertions(+), 21 deletions(-)

diff --git a/iocore/net/I_UDPNet.h b/iocore/net/I_UDPNet.h
index 846c3a7..289a87f 100644
--- a/iocore/net/I_UDPNet.h
+++ b/iocore/net/I_UDPNet.h
@@ -63,6 +63,7 @@ public:
      @param c Continuation that is called back with newly created
      socket.
      @param addr Address to bind (includes port)
+     @param fd File descriptor to use (if exists)
      @param send_bufsize (optional) Socket buffer size for sending.
      Limits how much outstanding data to OS before it is able to send
      to the NIC.
@@ -71,7 +72,7 @@ public:
      @return Action* Always returns ACTION_RESULT_DONE if socket was
      created successfully, or ACTION_IO_ERROR if not.
   */
-  inkcoreapi Action *UDPBind(Continuation *c, sockaddr const *addr, int send_bufsize = 0, int recv_bufsize = 0);
+  inkcoreapi Action *UDPBind(Continuation *c, sockaddr const *addr, int fd = -1, int send_bufsize = 0, int recv_bufsize = 0);
 
   // Regarding sendto_re, sendmsg_re, recvfrom_re:
   // * You may be called back on 'c' with completion or error status.
diff --git a/iocore/net/QUICNetProcessor.cc b/iocore/net/QUICNetProcessor.cc
index c14e000..a0c706a 100644
--- a/iocore/net/QUICNetProcessor.cc
+++ b/iocore/net/QUICNetProcessor.cc
@@ -215,7 +215,7 @@ QUICNetProcessor::main_accept(Continuation *cont, SOCKET fd, AcceptOptions const
   na->init_accept();
 
   SCOPED_MUTEX_LOCK(lock, na->mutex, this_ethread());
-  udpNet.UDPBind((Continuation *)na, &na->server.accept_addr.sa, 1048576, 1048576);
+  udpNet.UDPBind((Continuation *)na, &na->server.accept_addr.sa, fd, 1048576, 1048576);
 
   return na->action_.get();
 }
diff --git a/iocore/net/UnixUDPNet.cc b/iocore/net/UnixUDPNet.cc
index 64ed2ec..6b82104 100644
--- a/iocore/net/UnixUDPNet.cc
+++ b/iocore/net/UnixUDPNet.cc
@@ -735,20 +735,24 @@ HardError:
 }
 
 Action *
-UDPNetProcessor::UDPBind(Continuation *cont, sockaddr const *addr, int send_bufsize, int recv_bufsize)
+UDPNetProcessor::UDPBind(Continuation *cont, sockaddr const *addr, int fd, int send_bufsize, int recv_bufsize)
 {
   int res              = 0;
-  int fd               = -1;
   UnixUDPConnection *n = nullptr;
   IpEndpoint myaddr;
   int myaddr_len     = sizeof(myaddr);
   PollCont *pc       = nullptr;
   PollDescriptor *pd = nullptr;
+  bool need_bind     = true;
 
-  if ((res = socketManager.socket(addr->sa_family, SOCK_DGRAM, 0)) < 0) {
-    goto Lerror;
+  if (fd == -1) {
+    if ((res = socketManager.socket(addr->sa_family, SOCK_DGRAM, 0)) < 0) {
+      goto Lerror;
+    }
+    fd = res;
+  } else {
+    need_bind = false;
   }
-  fd = res;
   if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
     goto Lerror;
   }
@@ -798,11 +802,12 @@ UDPNetProcessor::UDPBind(Continuation *cont, sockaddr const *addr, int send_bufs
     }
   }
 
-  if (ats_is_ip6(addr) && safe_setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, SOCKOPT_ON, sizeof(int)) < 0) {
+  if (need_bind && ats_is_ip6(addr) && safe_setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, SOCKOPT_ON, sizeof(int)) < 0) {
     goto Lerror;
   }
 
-  if (socketManager.ink_bind(fd, addr, ats_ip_size(addr)) < 0) {
+  if (need_bind && (socketManager.ink_bind(fd, addr, ats_ip_size(addr)) < 0)) {
+    Debug("udpnet", "ink_bind failed");
     goto Lerror;
   }
 
diff --git a/iocore/net/test_I_UDPNet.cc b/iocore/net/test_I_UDPNet.cc
index 3971f99..9f50efe 100644
--- a/iocore/net/test_I_UDPNet.cc
+++ b/iocore/net/test_I_UDPNet.cc
@@ -61,7 +61,7 @@ EchoServer::start()
   addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
   addr.sin_port        = 0;
 
-  udpNet.UDPBind(static_cast<Continuation *>(this), reinterpret_cast<sockaddr const *>(&addr), 1048576, 1048576);
+  udpNet.UDPBind(static_cast<Continuation *>(this), reinterpret_cast<sockaddr const *>(&addr), -1, 1048576, 1048576);
 
   return true;
 }
diff --git a/mgmt/LocalManager.cc b/mgmt/LocalManager.cc
index 652ff47..5f55df3 100644
--- a/mgmt/LocalManager.cc
+++ b/mgmt/LocalManager.cc
@@ -941,29 +941,91 @@ LocalManager::listenForProxy()
   // We are not already bound, bind the port
   for (auto &p : lmgmt->m_proxy_ports) {
     if (ts::NO_FD == p.m_fd) {
-      this->bindProxyPort(p);
+      // Check the protocol (TCP or UDP) and create an appropriate socket
+      if (p.isQUIC()) {
+        this->bindUdpProxyPort(p);
+      } else {
+        this->bindTcpProxyPort(p);
+      }
     }
 
-    // read backlog configuration value and overwrite the default value if found
-    bool found;
     std::string_view fam{ats_ip_family_name(p.m_family)};
-    RecInt backlog = REC_readInteger("proxy.config.net.listen_backlog", &found);
-    backlog        = (found && backlog >= 0) ? backlog : ats_tcp_somaxconn();
+    if (p.isQUIC()) {
+      // Can we do something like listen backlog for QUIC(UDP) ??
+      // Do nothing for now
+    } else {
+      // read backlog configuration value and overwrite the default value if found
+      bool found;
+      RecInt backlog = REC_readInteger("proxy.config.net.listen_backlog", &found);
+      backlog        = (found && backlog >= 0) ? backlog : ats_tcp_somaxconn();
 
-    if ((listen(p.m_fd, backlog)) < 0) {
-      mgmt_fatal(errno, "[LocalManager::listenForProxy] Unable to listen on port: %d (%.*s)\n", p.m_port, fam.size(), fam.data());
+      if ((listen(p.m_fd, backlog)) < 0) {
+        mgmt_fatal(errno, "[LocalManager::listenForProxy] Unable to listen on port: %d (%.*s)\n", p.m_port, fam.size(), fam.data());
+      }
     }
+
     mgmt_log("[LocalManager::listenForProxy] Listening on port: %d (%.*s)\n", p.m_port, fam.size(), fam.data());
   }
   return;
 }
 
 /*
- * bindProxyPort()
+ * bindUdpProxyPort()
+ *  Function binds the accept port of the proxy
+ */
+void
+LocalManager::bindUdpProxyPort(HttpProxyPort &port)
+{
+  int one  = 1;
+  int priv = (port.m_port < 1024 && 0 != geteuid()) ? ElevateAccess::LOW_PORT_PRIVILEGE : 0;
+
+  ElevateAccess access(priv);
+
+  if ((port.m_fd = socket(port.m_family, SOCK_DGRAM, 0)) < 0) {
+    mgmt_fatal(0, "[bindProxyPort] Unable to create socket : %s\n", strerror(errno));
+  }
+
+  if (port.m_family == AF_INET6) {
+    if (setsockopt(port.m_fd, IPPROTO_IPV6, IPV6_V6ONLY, SOCKOPT_ON, sizeof(int)) < 0) {
+      mgmt_log("[bindProxyPort] Unable to set socket options: %d : %s\n", port.m_port, strerror(errno));
+    }
+  }
+  if (setsockopt(port.m_fd, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<char *>(&one), sizeof(int)) < 0) {
+    mgmt_fatal(0, "[bindProxyPort] Unable to set socket options: %d : %s\n", port.m_port, strerror(errno));
+  }
+
+  IpEndpoint ip;
+  if (port.m_inbound_ip.isValid()) {
+    ip.assign(port.m_inbound_ip);
+  } else if (AF_INET6 == port.m_family) {
+    if (m_inbound_ip6.isValid()) {
+      ip.assign(m_inbound_ip6);
+    } else {
+      ip.setToAnyAddr(AF_INET6);
+    }
+  } else if (AF_INET == port.m_family) {
+    if (m_inbound_ip4.isValid()) {
+      ip.assign(m_inbound_ip4);
+    } else {
+      ip.setToAnyAddr(AF_INET);
+    }
+  } else {
+    mgmt_fatal(0, "[bindProxyPort] Proxy port with invalid address type %d\n", port.m_family);
+  }
+  ip.port() = htons(port.m_port);
+  if (bind(port.m_fd, &ip.sa, ats_ip_size(&ip)) < 0) {
+    mgmt_fatal(0, "[bindProxyPort] Unable to bind socket: %d : %s\n", port.m_port, strerror(errno));
+  }
+
+  Debug("lm", "[bindProxyPort] Successfully bound proxy port %d", port.m_port);
+}
+
+/*
+ * bindTcpProxyPort()
  *  Function binds the accept port of the proxy
  */
 void
-LocalManager::bindProxyPort(HttpProxyPort &port)
+LocalManager::bindTcpProxyPort(HttpProxyPort &port)
 {
   int one  = 1;
   int priv = (port.m_port < 1024 && 0 != geteuid()) ? ElevateAccess::LOW_PORT_PRIVILEGE : 0;
diff --git a/mgmt/LocalManager.h b/mgmt/LocalManager.h
index 4c9cb37..f5121a4 100644
--- a/mgmt/LocalManager.h
+++ b/mgmt/LocalManager.h
@@ -76,7 +76,8 @@ public:
   void processEventQueue();
   bool startProxy(const char *onetime_options);
   void listenForProxy();
-  void bindProxyPort(HttpProxyPort &);
+  void bindUdpProxyPort(HttpProxyPort &);
+  void bindTcpProxyPort(HttpProxyPort &);
   void closeProxyPorts();
 
   void mgmtCleanup();
diff --git a/src/traffic_server/InkIOCoreAPI.cc b/src/traffic_server/InkIOCoreAPI.cc
index 5a52101..82adea6 100644
--- a/src/traffic_server/InkIOCoreAPI.cc
+++ b/src/traffic_server/InkIOCoreAPI.cc
@@ -443,7 +443,7 @@ INKUDPBind(TSCont contp, unsigned int ip, int port)
   ats_ip4_set(&addr, ip, htons(port));
 
   return reinterpret_cast<TSAction>(
-    udpNet.UDPBind((Continuation *)contp, ats_ip_sa_cast(&addr), INK_ETHERNET_MTU_SIZE, INK_ETHERNET_MTU_SIZE));
+    udpNet.UDPBind((Continuation *)contp, ats_ip_sa_cast(&addr), -1, INK_ETHERNET_MTU_SIZE, INK_ETHERNET_MTU_SIZE));
 }
 
 TSAction