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

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


The following commit(s) were added to refs/heads/master by this push:
     new cdcd881  Adds a new log tag for the MPTCP state of a connection
cdcd881 is described below

commit cdcd881e48bc25745d45f1c33a5f3ffc5d906d74
Author: Leif Hedstrom <zw...@apache.org>
AuthorDate: Fri Mar 15 09:08:42 2019 -0600

    Adds a new log tag for the MPTCP state of a connection
    
    Possible values are:
    
        -1 == MPTCP was not enabled on the listening port
         0 == MPTCP was enabled, but not negotiated
         1 == MPTCP was enabled, and succesfully negotiated
---
 doc/admin-guide/logging/formatting.en.rst | 13 +++++++++----
 include/tscore/ink_platform.h             |  9 +++++++++
 iocore/net/I_NetProcessor.h               |  6 ++++++
 iocore/net/I_NetVConnection.h             | 18 ++++++++++++++++--
 iocore/net/P_UnixNetVConnection.h         | 16 ++++++++++++++++
 iocore/net/UnixNetAccept.cc               | 10 ++++++++++
 iocore/net/UnixNetProcessor.cc            |  1 +
 mgmt/LocalManager.cc                      | 12 +++---------
 proxy/PluginVC.cc                         |  6 ++++++
 proxy/PluginVC.h                          |  1 +
 proxy/http/HttpProxyServerMain.cc         |  1 +
 proxy/http/HttpSM.cc                      | 11 +++++++----
 proxy/http/HttpSM.h                       | 30 +++++++++++++++---------------
 proxy/logging/Log.cc                      |  5 +++++
 proxy/logging/LogAccess.cc                | 15 +++++++++++++++
 proxy/logging/LogAccess.h                 |  1 +
 16 files changed, 121 insertions(+), 34 deletions(-)

diff --git a/doc/admin-guide/logging/formatting.en.rst 
b/doc/admin-guide/logging/formatting.en.rst
index 1a4bce0..1217663 100644
--- a/doc/admin-guide/logging/formatting.en.rst
+++ b/doc/admin-guide/logging/formatting.en.rst
@@ -45,7 +45,7 @@ The return value from the ``format`` function is the log 
format object which
 may then be supplied to the appropriate ``log.*`` functions that define your
 logging destinations.
 
-A very simple exampe, which contains only the timestamp of when the event began
+A very simple example, which contains only the timestamp of when the event 
began
 and the canonical URL of the request, would look like:
 
 .. code:: yaml
@@ -233,7 +233,7 @@ Error Code
 The log fields of error code which is triggered session close or
 transaction close. The first byte of this field indicates that the error
 code is session level (``S``) or transaction level (``T``).
-When no error code is received or transmitted, these fileds are ``-``.
+When no error code is received or transmitted, these fields are ``-``.
 For HTTP/2, error code are described in RFC 7540 section 7.
 
 ===== =============== =========================================================
@@ -660,6 +660,7 @@ TCP Details
 ~~~~~~~~~~~
 
 .. _cqtr:
+.. _cqmpt:
 
 The following logging fields reveal information about the TCP layer of client,
 proxy, and origin server connections.
@@ -670,6 +671,10 @@ Field Source         Description
 cqtr  Client Request TCP reused status of the connection between the client and
                      |TS| proxy, indicating whether the request was delivered
                      through an already established connection.
+cqmpt Client Request Indicates the MPTCP state of the connection. ``-1`` means
+                     MPTCP was not enabled on the listening port, whereas ``0``
+                     and ``1`` indicates whether MPTCP was successfully
+                     negotiated or not.
 ===== ============== ==========================================================
 
 .. _admin-logging-fields-time:
@@ -698,7 +703,7 @@ The logging fields expose a variety of timing related 
information about client,
 proxy, and origin transactions. Variants of some of the fields provide timing
 resolution of the same underlying detail in milliseconds and seconds (both
 fractional and rounded-down integers). These variants are particularly useful
-in accomodating the emulation of other HTTP proxy softwares' logging formats.
+in accommodating the emulation of other HTTP proxy softwares' logging formats.
 
 Other fields in this category provide variously formatted timestamps of
 particular events within the current transaction (e.g. the time at which a
@@ -731,7 +736,7 @@ ms    Proxy                   Timestamp in milliseconds of 
a specific milestone
                               which milestone to use.
 msdms Proxy                   Difference in milliseconds between the timestamps
                               of two milestones. See note below about
-                              specifying which miletones to use.
+                              specifying which milestones to use.
 stms  Proxy-Origin Connection Time (in milliseconds) spent accessing the origin
                               server. Measured from the time the connection
                               between proxy and origin is established to the
diff --git a/include/tscore/ink_platform.h b/include/tscore/ink_platform.h
index a7e0e8a..6bef79d 100644
--- a/include/tscore/ink_platform.h
+++ b/include/tscore/ink_platform.h
@@ -190,3 +190,12 @@ typedef unsigned int in_addr_t;
        // on various OSs (linux-4096,osx/bsd-1024,
        //                 windows-260,etc)
 #endif
+
+// This is a little bit of a hack for now, until MPTCP has landed upstream in 
Linux land.
+#ifndef MPTCP_ENABLED
+#if defined(linux)
+#define MPTCP_ENABLED 42
+#else
+#define MPTCP_ENABLED 0
+#endif
+#endif
diff --git a/iocore/net/I_NetProcessor.h b/iocore/net/I_NetProcessor.h
index b8dee4e..570e7f3 100644
--- a/iocore/net/I_NetProcessor.h
+++ b/iocore/net/I_NetProcessor.h
@@ -97,6 +97,12 @@ public:
     */
     bool f_inbound_transparent;
 
+    /** MPTCP enabled on listener.
+        @internal For logging and metrics purposes to know whether the
+        listener enabled MPTCP or not.
+    */
+    bool f_mptcp;
+
     /// Proxy Protocol enabled
     bool f_proxy_protocol;
 
diff --git a/iocore/net/I_NetVConnection.h b/iocore/net/I_NetVConnection.h
index e906568..e1e9504 100644
--- a/iocore/net/I_NetVConnection.h
+++ b/iocore/net/I_NetVConnection.h
@@ -21,9 +21,11 @@
   limitations under the License.
 
  */
-
 #pragma once
 
+#include <string_view>
+#include <optional>
+
 #include "tscore/ink_inet.h"
 #include "I_Action.h"
 #include "I_VConnection.h"
@@ -32,7 +34,6 @@
 #include "I_IOBuffer.h"
 #include "I_Socks.h"
 #include "ts/apidefs.h"
-#include <string_view>
 #include "YamlSNIConfig.h"
 #include "tscpp/util/TextView.h"
 #include "tscore/IpMap.h"
@@ -649,6 +650,9 @@ public:
   /** Set remote sock addr struct. */
   virtual void set_remote_addr(const sockaddr *) = 0;
 
+  /** Set the MPTCP state for this connection */
+  virtual void set_mptcp_state() = 0;
+
   // for InkAPI
   bool
   get_is_internal_request() const
@@ -668,6 +672,14 @@ public:
   {
     return is_transparent;
   }
+
+  /// Get the MPTCP state of the VC.
+  std::optional<bool>
+  get_mptcp_state() const
+  {
+    return mptcp_state;
+  }
+
   /// Set the transparency state.
   void
   set_is_transparent(bool state = true)
@@ -823,6 +835,8 @@ protected:
   bool is_transparent = false;
   /// Set if proxy protocol is enabled
   bool is_proxy_protocol = false;
+  /// This is essentially a tri-state, we leave it undefined to mean no MPTCP 
support
+  std::optional<bool> mptcp_state;
   /// Set if the next write IO that empties the write buffer should generate 
an event.
   int write_buffer_empty_event = 0;
   /// NetVConnection Context.
diff --git a/iocore/net/P_UnixNetVConnection.h 
b/iocore/net/P_UnixNetVConnection.h
index f56a208..46111bc 100644
--- a/iocore/net/P_UnixNetVConnection.h
+++ b/iocore/net/P_UnixNetVConnection.h
@@ -292,6 +292,7 @@ public:
   ink_hrtime get_active_timeout() override;
 
   void set_local_addr() override;
+  void set_mptcp_state() override;
   void set_remote_addr() override;
   void set_remote_addr(const sockaddr *) override;
   int set_tcp_init_cwnd(int init_cwnd) override;
@@ -347,6 +348,21 @@ UnixNetVConnection::set_local_addr()
   ATS_UNUSED_RETURN(safe_getsockname(con.fd, &local_addr.sa, &local_sa_size));
 }
 
+// Update the internal VC state variable for MPTCP
+inline void
+UnixNetVConnection::set_mptcp_state()
+{
+  int mptcp_enabled      = -1;
+  int mptcp_enabled_size = sizeof(mptcp_enabled);
+
+  if (0 == safe_getsockopt(con.fd, IPPROTO_TCP, MPTCP_ENABLED, (char 
*)&mptcp_enabled, &mptcp_enabled_size)) {
+    Debug("socket_mptcp", "MPTCP socket state: %d", mptcp_enabled);
+    mptcp_state = mptcp_enabled > 0 ? true : false;
+  } else {
+    Debug("socket_mptcp", "MPTCP failed getsockopt(): %s", strerror(errno));
+  }
+}
+
 inline ink_hrtime
 UnixNetVConnection::get_active_timeout()
 {
diff --git a/iocore/net/UnixNetAccept.cc b/iocore/net/UnixNetAccept.cc
index 0164d64..a1141e4 100644
--- a/iocore/net/UnixNetAccept.cc
+++ b/iocore/net/UnixNetAccept.cc
@@ -117,6 +117,9 @@ net_accept(NetAccept *na, void *ep, bool blockable)
     vc->set_is_transparent(na->opt.f_inbound_transparent);
     vc->set_is_proxy_protocol(na->opt.f_proxy_protocol);
     vc->set_context(NET_VCONNECTION_IN);
+    if (na->opt.f_mptcp) {
+      vc->set_mptcp_state(); // Try to get the MPTCP state, and update 
accordingly
+    }
 #ifdef USE_EDGE_TRIGGER
     // Set the vc as triggered and place it in the read ready queue later in 
case there is already data on the socket.
     if (na->server.http_accept_filter) {
@@ -354,6 +357,9 @@ NetAccept::do_blocking_accept(EThread *t)
     vc->options.ip_family   = opt.ip_family;
     vc->apply_options();
     vc->set_context(NET_VCONNECTION_IN);
+    if (opt.f_mptcp) {
+      vc->set_mptcp_state(); // Try to get the MPTCP state, and update 
accordingly
+    }
     vc->accept_object = this;
 #ifdef USE_EDGE_TRIGGER
     // Set the vc as triggered and place it in the read ready queue later in 
case there is already data on the socket.
@@ -503,6 +509,10 @@ NetAccept::acceptFastEvent(int event, void *ep)
     vc->options.ip_family   = opt.ip_family;
     vc->apply_options();
     vc->set_context(NET_VCONNECTION_IN);
+    if (opt.f_mptcp) {
+      vc->set_mptcp_state(); // Try to get the MPTCP state, and update 
accordingly
+    }
+
 #ifdef USE_EDGE_TRIGGER
     // Set the vc as triggered and place it in the read ready queue later in 
case there is already data on the socket.
     if (server.http_accept_filter) {
diff --git a/iocore/net/UnixNetProcessor.cc b/iocore/net/UnixNetProcessor.cc
index 436e6fa..e9896d5 100644
--- a/iocore/net/UnixNetProcessor.cc
+++ b/iocore/net/UnixNetProcessor.cc
@@ -51,6 +51,7 @@ NetProcessor::AcceptOptions::reset()
   packet_tos            = 0;
   tfo_queue_length      = 0;
   f_inbound_transparent = false;
+  f_mptcp               = false;
   f_proxy_protocol      = false;
   return *this;
 }
diff --git a/mgmt/LocalManager.cc b/mgmt/LocalManager.cc
index a9205be..8caf6f0 100644
--- a/mgmt/LocalManager.cc
+++ b/mgmt/LocalManager.cc
@@ -47,14 +47,6 @@ using namespace std::literals;
 static const std::string_view MGMT_OPT{"-M"};
 static const std::string_view RUNROOT_OPT{"--run-root="};
 
-#ifndef MPTCP_ENABLED
-#if defined(linux)
-#define MPTCP_ENABLED 42
-#else
-#define MPTCP_ENABLED 0
-#endif
-#endif
-
 void
 LocalManager::mgmtCleanup()
 {
@@ -1043,11 +1035,13 @@ LocalManager::bindProxyPort(HttpProxyPort &port)
     err = setsockopt(port.m_fd, IPPROTO_TCP, MPTCP_ENABLED, &one, sizeof(one));
     if (err < 0) {
       mgmt_log("[bindProxyPort] Unable to enable MPTCP: %s\n", 
strerror(errno));
+      Debug("lm_mptcp", "[bindProxyPort] Unable to enable MPTCP: %s", 
strerror(errno));
     } else {
       mgmt_log("[bindProxyPort] Successfully enabled MPTCP on %d\n", 
port.m_port);
+      Debug("lm_mptcp", "[bindProxyPort] Successfully enabled MPTCP on %d\n", 
port.m_port);
     }
 #else
-    Debug("lm", "[bindProxyPort] Multipath TCP requested but not configured on 
this host");
+    Debug("lm_mptcp", "[bindProxyPort] Multipath TCP requested but not 
configured on this host");
 #endif
   }
 
diff --git a/proxy/PluginVC.cc b/proxy/PluginVC.cc
index b4a62e5..79abc43 100644
--- a/proxy/PluginVC.cc
+++ b/proxy/PluginVC.cc
@@ -963,6 +963,12 @@ PluginVC::set_remote_addr(const sockaddr * /* new_sa 
ATS_UNUSED */)
   return;
 }
 
+void
+PluginVC::set_mptcp_state()
+{
+  return;
+}
+
 int
 PluginVC::set_tcp_init_cwnd(int /* init_cwnd ATS_UNUSED */)
 {
diff --git a/proxy/PluginVC.h b/proxy/PluginVC.h
index d620549..6ee6b4d 100644
--- a/proxy/PluginVC.h
+++ b/proxy/PluginVC.h
@@ -102,6 +102,7 @@ public:
   void set_local_addr() override;
   void set_remote_addr() override;
   void set_remote_addr(const sockaddr *) override;
+  void set_mptcp_state() override;
   int set_tcp_init_cwnd(int init_cwnd) override;
   int set_tcp_congestion_control(int) override;
 
diff --git a/proxy/http/HttpProxyServerMain.cc 
b/proxy/http/HttpProxyServerMain.cc
index 7863833..11abf90 100644
--- a/proxy/http/HttpProxyServerMain.cc
+++ b/proxy/http/HttpProxyServerMain.cc
@@ -158,6 +158,7 @@ make_net_accept_options(const HttpProxyPort *port, unsigned 
nthreads)
 
   if (port) {
     net.f_inbound_transparent = port->m_inbound_transparent_p;
+    net.f_mptcp               = port->m_mptcp;
     net.ip_family             = port->m_family;
     net.local_port            = port->m_port;
     net.f_proxy_protocol      = port->m_proxy_protocol;
diff --git a/proxy/http/HttpSM.cc b/proxy/http/HttpSM.cc
index 81ec27f..3b9ae71 100644
--- a/proxy/http/HttpSM.cc
+++ b/proxy/http/HttpSM.cc
@@ -465,12 +465,15 @@ HttpSM::attach_client_session(ProxyClientTransaction 
*client_vc, IOBufferReader
       _client_connection_id = p->connection_id();
     }
   }
-  // We've already verified that the netvc is !nullptr above, and netvc == 
ua_txn->get_netvc()
-  is_internal = netvc->get_is_internal_request();
 
-  // Collect log & stats information
-  client_tcp_reused         = !(ua_txn->is_first_transaction());
+  // Collect log & stats information. We've already verified that the netvc is 
!nullptr above,
+  // and netvc == ua_txn->get_netvc().
   SSLNetVConnection *ssl_vc = dynamic_cast<SSLNetVConnection *>(netvc);
+
+  is_internal       = netvc->get_is_internal_request();
+  mptcp_state       = netvc->get_mptcp_state();
+  client_tcp_reused = !(ua_txn->is_first_transaction());
+
   if (ssl_vc != nullptr) {
     client_connection_is_ssl = true;
     client_ssl_reused        = ssl_vc->getSSLSessionCacheHit();
diff --git a/proxy/http/HttpSM.h b/proxy/http/HttpSM.h
index 76a0d13..30ace9e 100644
--- a/proxy/http/HttpSM.h
+++ b/proxy/http/HttpSM.h
@@ -29,9 +29,11 @@
 
 
  ****************************************************************************/
-
 #pragma once
 
+#include <string_view>
+#include <optional>
+
 #include "tscore/ink_platform.h"
 #include "P_EventSystem.h"
 #include "HttpCacheSM.h"
@@ -41,9 +43,7 @@
 #include "InkAPIInternal.h"
 #include "../ProxyClientTransaction.h"
 #include "HdrUtils.h"
-#include <string_view>
 #include "tscore/History.h"
-//#include "AuthHttpAdapter.h"
 
 #define HTTP_API_CONTINUE (INK_API_EVENT_EVENTS_START + 0)
 #define HTTP_API_ERROR (INK_API_EVENT_EVENTS_START + 1)
@@ -310,12 +310,12 @@ public:
 
   // YTS Team, yamsat Plugin
   bool enable_redirection = false; // To check if redirection is enabled
+  bool post_failed        = false; // Added to identify post failure
+  bool debug_on           = false; // Transaction specific debug flag
   char *redirect_url    = nullptr; // url for force redirect (provide users a 
functionality to redirect to another url when needed)
   int redirect_url_len  = 0;
-  int redirection_tries = 0;        // To monitor number of redirections
-  int64_t transfered_bytes = 0;     // Added to calculate POST data
-  bool post_failed         = false; // Added to identify post failure
-  bool debug_on            = false; // Transaction specific debug flag
+  int redirection_tries = 0;    // To monitor number of redirections
+  int64_t transfered_bytes = 0; // Added to calculate POST data
 
   // Tunneling request to plugin
   HttpPluginTunnel_t plugin_tunnel_type = HTTP_NO_PLUGIN_TUNNEL;
@@ -335,9 +335,9 @@ public:
   void postbuf_copy_partial_data();
   void postbuf_init(IOBufferReader *ua_reader);
   void set_postbuf_done(bool done);
+  IOBufferReader *get_postbuf_clone_reader();
   bool get_postbuf_done();
   bool is_postbuf_valid();
-  IOBufferReader *get_postbuf_clone_reader();
 
 protected:
   int reentrancy_count = 0;
@@ -536,17 +536,17 @@ public:
   int pushed_response_hdr_bytes      = 0;
   int64_t pushed_response_body_bytes = 0;
   bool client_tcp_reused             = false;
-  // Info about client's SSL connection.
-  bool client_ssl_reused          = false;
-  bool client_connection_is_ssl   = false;
-  bool is_internal                = false;
+  bool client_ssl_reused             = false;
+  bool client_connection_is_ssl      = false;
+  bool is_internal                   = false;
+  bool server_connection_is_ssl      = false;
+  bool is_waiting_for_full_body      = false;
+  bool is_using_post_buffer          = false;
+  std::optional<bool> mptcp_state; // Don't initialize, that marks it as "not 
defined".
   const char *client_protocol     = "-";
   const char *client_sec_protocol = "-";
   const char *client_cipher_suite = "-";
   int server_transact_count       = 0;
-  bool server_connection_is_ssl   = false;
-  bool is_waiting_for_full_body   = false;
-  bool is_using_post_buffer       = false;
 
   TransactionMilestones milestones;
   ink_hrtime api_timer = 0;
diff --git a/proxy/logging/Log.cc b/proxy/logging/Log.cc
index b3a2354..04038f1 100644
--- a/proxy/logging/Log.cc
+++ b/proxy/logging/Log.cc
@@ -502,6 +502,11 @@ Log::init_fields()
   global_field_list.add(field, false);
   field_symbol_hash.emplace("cqint", field);
 
+  field = new LogField("client_req_mptcp", "cqmpt", LogField::sINT, 
&LogAccess::marshal_client_req_mptcp_state,
+                       &LogAccess::unmarshal_int_to_str);
+  global_field_list.add(field, false);
+  field_symbol_hash.emplace("cqmpt", field);
+
   field = new LogField("client_sec_protocol", "cqssv", LogField::STRING, 
&LogAccess::marshal_client_security_protocol,
                        (LogField::UnmarshalFunc)&LogAccess::unmarshal_str);
   global_field_list.add(field, false);
diff --git a/proxy/logging/LogAccess.cc b/proxy/logging/LogAccess.cc
index 4fc737b..202cfaa 100644
--- a/proxy/logging/LogAccess.cc
+++ b/proxy/logging/LogAccess.cc
@@ -1725,6 +1725,21 @@ LogAccess::marshal_client_req_is_internal(char *buf)
   return INK_MIN_ALIGN;
 }
 
+int
+LogAccess::marshal_client_req_mptcp_state(char *buf)
+{
+  if (buf) {
+    int val = -1;
+
+    if (m_http_sm->mptcp_state.has_value()) {
+      val = m_http_sm->mptcp_state.value() ? 1 : 0;
+    } else {
+    }
+    marshal_int(buf, val);
+  }
+  return INK_MIN_ALIGN;
+}
+
 /*-------------------------------------------------------------------------
   -------------------------------------------------------------------------*/
 
diff --git a/proxy/logging/LogAccess.h b/proxy/logging/LogAccess.h
index 1e05282..c915204 100644
--- a/proxy/logging/LogAccess.h
+++ b/proxy/logging/LogAccess.h
@@ -150,6 +150,7 @@ public:
   inkcoreapi int marshal_client_req_is_ssl(char *);             // INT
   inkcoreapi int marshal_client_req_ssl_reused(char *);         // INT
   inkcoreapi int marshal_client_req_is_internal(char *);        // INT
+  inkcoreapi int marshal_client_req_mptcp_state(char *);        // INT
   inkcoreapi int marshal_client_security_protocol(char *);      // STR
   inkcoreapi int marshal_client_security_cipher_suite(char *);  // STR
   inkcoreapi int marshal_client_finish_status_code(char *);     // INT

Reply via email to