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 2021/04/10 22:05:29 UTC

[trafficserver] branch 9.1.x updated: Adding TCP Info header support to header rewrite (#7516)

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

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


The following commit(s) were added to refs/heads/9.1.x by this push:
     new 702c387  Adding TCP Info header support to header rewrite (#7516)
702c387 is described below

commit 702c387b56103eb780147055ffd397cb3c817091
Author: dbhat <db...@users.noreply.github.com>
AuthorDate: Wed Mar 31 20:28:32 2021 -0700

    Adding TCP Info header support to header rewrite (#7516)
    
    * Adding TCP Info header support to header rewrite
    
    Adding documentation for TCP Info support for header rewrite plugin
    
    * Adding TCP Info header support to header rewrite
    
    Adding documentation for TCP Info support for header rewrite plugin
    
    * fixing indentation in doc
    
    * adding header file tcp info
    
    * adding header file tcp info
    
    fixing indentation in doc
    
    * adding header file tcp info
    
    fixing indentation in doc
    
    * Fixing headers where TCP info is written
    
    * adding message for internal transaction
    
    * Adding documenation for TCP-INFO in header rewrite
    
    * Fixing internal header debug message for TCP Info
    
    * adding message for internal transaction
    
    Co-authored-by: Divya Bhat <di...@apple.com>
    (cherry picked from commit ebd9d38fbed5c13123b92641209da3cf92d201ef)
---
 doc/admin-guide/plugins/header_rewrite.en.rst | 18 ++++++
 plugins/header_rewrite/conditions.cc          | 84 ++++++++++++++++++++++++++-
 plugins/header_rewrite/conditions.h           | 22 ++++++-
 plugins/header_rewrite/factory.cc             |  2 +
 plugins/header_rewrite/header_rewrite.cc      |  6 ++
 plugins/header_rewrite/parser.cc              |  8 +++
 plugins/header_rewrite/resources.cc           | 18 ++++++
 plugins/header_rewrite/statement.cc           |  2 +
 8 files changed, 158 insertions(+), 2 deletions(-)

diff --git a/doc/admin-guide/plugins/header_rewrite.en.rst b/doc/admin-guide/plugins/header_rewrite.en.rst
index 9db100a..40f86a3 100644
--- a/doc/admin-guide/plugins/header_rewrite.en.rst
+++ b/doc/admin-guide/plugins/header_rewrite.en.rst
@@ -491,6 +491,15 @@ SSN-TXN-COUNT
 Returns the number of transactions between the Traffic Server proxy and the origin server from a single session.
 Any value greater than zero indicates connection reuse.
 
+TCP-INFO
+~~~~~~~~
+::
+
+	cond %{<name>}
+        add-header @PropertyName "%{TCP-INFO}"
+
+This operation records TCP Info struct field values as an Internal remap as well as global header at the event hook specified by the condition. Supported hook conditions include TXN_START_HOOK, SEND_RESPONSE_HEADER_HOOK and TXN_CLOSE_HOOK in the Global plugin and REMAP_PSEUDO_HOOK, SEND_RESPONSE_HEADER_HOOK and TXN_CLOSE_HOOK in the Remap plugin. Conditions supported as request headers include TXN_START_HOOK and REMAP_PSEUDO_HOOK. The other conditions are supported as response headers. T [...]
+
 Condition Operands
 ------------------
 
@@ -935,6 +944,15 @@ cache updates may have been performed. This hook context provides a means to
 modify aspects of the response sent to a client, while still caching the
 original versions of those attributes delivered by the origin server.
 
+TXN_START_HOOK
+~~~~~~~~~~~~~~
+Rulesets are evaluated when |TS| receives a request and accepts it. This hook context indicates that a HTTP transaction is initiated and therefore, can only be enabled as a global plugin.
+
+TXN_CLOSE_HOOK
+~~~~~~~~~~~~~~
+
+Rulesets are evaluated when |TS| completes a transaction, i.e., after a response has been sent to the client. Therefore, header modifications at this hook condition only makes sense for internal headers.
+
 Affected Conditions
 -------------------
 
diff --git a/plugins/header_rewrite/conditions.cc b/plugins/header_rewrite/conditions.cc
index 84ce254..66c3e5d 100644
--- a/plugins/header_rewrite/conditions.cc
+++ b/plugins/header_rewrite/conditions.cc
@@ -32,6 +32,17 @@
 #include "conditions.h"
 #include "lulu.h"
 
+// This is a bit of a hack, to get the more linux specific tcp_info struct ...
+#if HAVE_STRUCT_LINUX_TCP_INFO
+#ifndef _LINUX_TCP_H
+#define _LINUX_TCP_H
+#endif
+#elif HAVE_NETINET_IN_H
+#ifndef _NETINET_TCP_H
+#define _NETINET_TCP_H
+#endif
+#endif
+
 // ConditionStatus
 void
 ConditionStatus::initialize(Parser &p)
@@ -1333,4 +1344,75 @@ ConditionSessionTransactCount::append_value(std::string &s, Resources const &res
     TSDebug(PLUGIN_NAME, "Appending SSN-TXN-COUNT %s to evaluation value %.*s", _qualifier.c_str(), length, value);
     s.append(value, length);
   }
-}
\ No newline at end of file
+}
+
+void
+ConditionTcpInfo::initialize(Parser &p)
+{
+  Condition::initialize(p);
+  TSDebug(PLUGIN_NAME, "Initializing TCP Info");
+  MatcherType *match     = new MatcherType(_cond_op);
+  std::string const &arg = p.get_arg();
+
+  match->set(strtol(arg.c_str(), nullptr, 10));
+  _matcher = match;
+}
+
+void
+ConditionTcpInfo::initialize_hooks()
+{
+  add_allowed_hook(TS_HTTP_TXN_START_HOOK);
+  add_allowed_hook(TS_HTTP_TXN_CLOSE_HOOK);
+  add_allowed_hook(TS_HTTP_SEND_RESPONSE_HDR_HOOK);
+}
+
+bool
+ConditionTcpInfo::eval(const Resources &res)
+{
+  std::string s;
+
+  append_value(s, res);
+  bool rval = static_cast<const Matchers<std::string> *>(_matcher)->test(s);
+
+  TSDebug(PLUGIN_NAME, "Evaluating TCP-Info: %s - rval: %d", s.c_str(), rval);
+
+  return rval;
+}
+
+void
+ConditionTcpInfo::append_value(std::string &s, Resources const &res)
+{
+#if defined(TCP_INFO) && defined(HAVE_STRUCT_TCP_INFO)
+  if (TSHttpTxnIsInternal(res.txnp)) {
+    TSDebug(PLUGIN_NAME, "No TCP-INFO available for internal transactions");
+    return;
+  }
+  TSReturnCode tsSsn;
+  int fd;
+  struct tcp_info info;
+  socklen_t tcp_info_len = sizeof(info);
+  tsSsn                  = TSHttpTxnClientFdGet(res.txnp, &fd);
+  if (tsSsn != TS_SUCCESS || fd <= 0) {
+    TSDebug(PLUGIN_NAME, "error getting the client socket fd from ssn");
+  }
+  if (getsockopt(fd, IPPROTO_TCP, TCP_INFO, &info, &tcp_info_len) != 0) {
+    TSDebug(PLUGIN_NAME, "getsockopt(%d, TCP_INFO) failed: %s", fd, strerror(errno));
+  }
+
+  if (tsSsn == TS_SUCCESS) {
+    if (tcp_info_len > 0) {
+      char buf[12 * 4 + 9]; // 4x uint32's + 4x "; " + '\0'
+#if !defined(freebsd) || defined(__GLIBC__)
+      snprintf(buf, sizeof(buf), "%" PRIu32 ";%" PRIu32 ";%" PRIu32 ";%" PRIu32 "", info.tcpi_rtt, info.tcpi_rto,
+               info.tcpi_snd_cwnd, info.tcpi_retrans);
+#else
+      snprintf(buf, sizeof(buf), "%" PRIu32 ";%" PRIu32 ";%" PRIu32 ";%" PRIu32 "", info.tcpi_rtt, info.tcpi_rto,
+               info.tcpi_snd_cwnd, info.__tcpi_retrans);
+#endif
+      s += buf;
+    }
+  }
+#else
+  s += "-";
+#endif
+}
diff --git a/plugins/header_rewrite/conditions.h b/plugins/header_rewrite/conditions.h
index 03f42d4..ed6c61f 100644
--- a/plugins/header_rewrite/conditions.h
+++ b/plugins/header_rewrite/conditions.h
@@ -562,4 +562,24 @@ public:
 
 protected:
   bool eval(const Resources &res) override;
-};
\ No newline at end of file
+};
+
+// Tcp Info
+class ConditionTcpInfo : public Condition
+{
+  typedef Matchers<int> MatcherType;
+
+public:
+  ConditionTcpInfo() { TSDebug(PLUGIN_NAME_DBG, "Calling CTOR for ConditionTcpInfo"); }
+
+  // noncopyable
+  ConditionTcpInfo(const ConditionTcpInfo &) = delete;
+  void operator=(const ConditionTcpInfo &) = delete;
+
+  void initialize(Parser &p) override;
+  void append_value(std::string &s, const Resources &res) override;
+
+protected:
+  bool eval(const Resources &res) override;
+  void initialize_hooks() override; // Return status only valid in certain hooks
+};
diff --git a/plugins/header_rewrite/factory.cc b/plugins/header_rewrite/factory.cc
index a5decc7..26f9a4f 100644
--- a/plugins/header_rewrite/factory.cc
+++ b/plugins/header_rewrite/factory.cc
@@ -139,6 +139,8 @@ condition_factory(const std::string &cond)
     c = new ConditionInbound();
   } else if (c_name == "SSN-TXN-COUNT") {
     c = new ConditionSessionTransactCount();
+  } else if (c_name == "TCP-INFO") {
+    c = new ConditionTcpInfo();
   } else {
     TSError("[%s] Unknown condition %s", PLUGIN_NAME, c_name.c_str());
     return nullptr;
diff --git a/plugins/header_rewrite/header_rewrite.cc b/plugins/header_rewrite/header_rewrite.cc
index a0e6707..85e0fee 100644
--- a/plugins/header_rewrite/header_rewrite.cc
+++ b/plugins/header_rewrite/header_rewrite.cc
@@ -279,6 +279,12 @@ cont_rewrite_headers(TSCont contp, TSEvent event, void *edata)
   case TS_EVENT_HTTP_SEND_RESPONSE_HDR:
     hook = TS_HTTP_SEND_RESPONSE_HDR_HOOK;
     break;
+  case TS_EVENT_HTTP_TXN_START:
+    hook = TS_HTTP_TXN_START_HOOK;
+    break;
+  case TS_EVENT_HTTP_TXN_CLOSE:
+    hook = TS_HTTP_TXN_CLOSE_HOOK;
+    break;
   default:
     TSError("[%s] unknown event for this plugin", PLUGIN_NAME);
     TSDebug(PLUGIN_NAME, "unknown event for this plugin");
diff --git a/plugins/header_rewrite/parser.cc b/plugins/header_rewrite/parser.cc
index cb6e2c5..701227e 100644
--- a/plugins/header_rewrite/parser.cc
+++ b/plugins/header_rewrite/parser.cc
@@ -244,6 +244,14 @@ Parser::cond_is_hook(TSHttpHookID &hook) const
     hook = TS_REMAP_PSEUDO_HOOK;
     return true;
   }
+  if ("TXN_START_HOOK" == _op) {
+    hook = TS_HTTP_TXN_START_HOOK;
+    return true;
+  }
+  if ("TXN_CLOSE_HOOK" == _op) {
+    hook = TS_HTTP_TXN_CLOSE_HOOK;
+    return true;
+  }
 
   return false;
 }
diff --git a/plugins/header_rewrite/resources.cc b/plugins/header_rewrite/resources.cc
index bc861c6..0578d3b 100644
--- a/plugins/header_rewrite/resources.cc
+++ b/plugins/header_rewrite/resources.cc
@@ -99,6 +99,24 @@ Resources::gather(const ResourceIDs ids, TSHttpHookID hook)
     }
     break;
 
+  case TS_HTTP_TXN_START_HOOK:
+    // Get TCP Info at transaction start
+    if (client_bufp && client_hdr_loc) {
+      TSDebug(PLUGIN_NAME, "\tAdding TXN client request header buffers for TXN Start instance");
+      bufp    = client_bufp;
+      hdr_loc = client_hdr_loc;
+    }
+    break;
+
+  case TS_HTTP_TXN_CLOSE_HOOK:
+    // Get TCP Info at transaction close
+    TSDebug(PLUGIN_NAME, "\tAdding TXN close buffers");
+    if (TSHttpTxnClientRespGet(txnp, &bufp, &hdr_loc) != TS_SUCCESS) {
+      TSDebug(PLUGIN_NAME, "could not gather bufp/hdr_loc for request");
+      return;
+    }
+    break;
+
   default:
     break;
   }
diff --git a/plugins/header_rewrite/statement.cc b/plugins/header_rewrite/statement.cc
index ee342dc..fd2c17f 100644
--- a/plugins/header_rewrite/statement.cc
+++ b/plugins/header_rewrite/statement.cc
@@ -69,6 +69,8 @@ Statement::initialize_hooks()
   add_allowed_hook(TS_HTTP_SEND_REQUEST_HDR_HOOK);
   add_allowed_hook(TS_HTTP_SEND_RESPONSE_HDR_HOOK);
   add_allowed_hook(TS_REMAP_PSEUDO_HOOK);
+  add_allowed_hook(TS_HTTP_TXN_START_HOOK);
+  add_allowed_hook(TS_HTTP_TXN_CLOSE_HOOK);
 }
 
 // Parse URL qualifiers, this one is special since it's used in a few places.