> On Oct 17, 2014, at 7:59 AM, sudhe...@apache.org wrote:
> 
> Repository: trafficserver
> Updated Branches:
>  refs/heads/master 609443dbe -> dee36e716
> 
> 
> [TS-2503]: Dynamic TLS Record Sizing for better page load latencies.
> The strategy used is essentially to use small TLS records that fit into a
> single TCP segment for the first ~1 MB of data, increase record size to 16 KB
> after that to optimize throughput, and then reset record size back to a single
> segment after ~1 second of inactivity—lather, rinse, repeat.
> 
> 
> Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo
> Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/dee36e71
> Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/dee36e71
> Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/dee36e71
> 
> Branch: refs/heads/master
> Commit: dee36e7163373c1d61bc6b97e529269dcde134c5
> Parents: 609443d
> Author: Sudheer Vinukonda <sudhe...@yahoo-inc.com>
> Authored: Fri Oct 17 14:57:15 2014 +0000
> Committer: Sudheer Vinukonda <sudhe...@yahoo-inc.com>
> Committed: Fri Oct 17 14:57:15 2014 +0000
> 
> ----------------------------------------------------------------------
> .../configuration/records.config.en.rst         |  7 ++++
> iocore/net/P_SSLNetVConnection.h                | 13 ++++++
> iocore/net/P_SSLUtils.h                         |  2 +
> iocore/net/SSLNetVConnection.cc                 | 43 +++++++++++++++++++-
> iocore/net/SSLUtils.cc                          |  4 ++
> 5 files changed, 68 insertions(+), 1 deletion(-)
> ----------------------------------------------------------------------
> 
> 
> http://git-wip-us.apache.org/repos/asf/trafficserver/blob/dee36e71/doc/reference/configuration/records.config.en.rst
> ----------------------------------------------------------------------
> diff --git a/doc/reference/configuration/records.config.en.rst 
> b/doc/reference/configuration/records.config.en.rst
> index 07244b7..ca30055 100644
> --- a/doc/reference/configuration/records.config.en.rst
> +++ b/doc/reference/configuration/records.config.en.rst
> @@ -2168,6 +2168,13 @@ SSL Termination
>   buffering at the SSL layer. The default of ``0`` means to always
>   write all available data into a single SSL record.
> 
> +  A value of ``-1`` means TLS record size is dynamically determined. The
> +  strategy employed is to use small TLS records that fit into a single
> +  TCP segment for the first ~1 MB of data, but, increase the record size to
> +  16 KB after that to optimize throughput. The record size is reset back to
> +  a single segment after ~1 second of inactivity and the record size ramping
> +  mechanism is repeated again.
> +
> .. ts:cv:: CONFIG proxy.config.ssl.session_cache INT 2
> 
>       Enables the SSL Session Cache:
> 
> http://git-wip-us.apache.org/repos/asf/trafficserver/blob/dee36e71/iocore/net/P_SSLNetVConnection.h
> ----------------------------------------------------------------------
> diff --git a/iocore/net/P_SSLNetVConnection.h 
> b/iocore/net/P_SSLNetVConnection.h
> index 51b7391..4a6d7c8 100644
> --- a/iocore/net/P_SSLNetVConnection.h
> +++ b/iocore/net/P_SSLNetVConnection.h
> @@ -52,6 +52,17 @@
> #define SSL_TLSEXT_ERR_NOACK 3
> #endif
> 
> +// TS-2503: dynamic TLS record sizing
> +// For smaller records, we should also reserve space for various TCP options
> +// (timestamps, SACKs.. up to 40 bytes [1]), and account for TLS record 
> overhead
> +// (another 20-60 bytes on average, depending on the negotiated ciphersuite 
> [2]).
> +// All in all: 1500 - 40 (IP) - 20 (TCP) - 40 (TCP options) - TLS overhead 
> (60-100)
> +// For larger records, the size is determined by TLS protocol record size
> +#define SSL_DEF_TLS_RECORD_SIZE               1300 // 1500 - 40 (IP) - 20 
> (TCP) - 40 (TCP options) - TLS overhead (60-100)
> +#define SSL_MAX_TLS_RECORD_SIZE              16383 // 2^14 - 1
> +#define SSL_DEF_TLS_RECORD_BYTE_THRESHOLD  1000000
> +#define SSL_DEF_TLS_RECORD_MSEC_THRESHOLD     1000
> +
> class SSLNextProtocolSet;
> struct SSLCertLookup;
> 
> @@ -105,6 +116,8 @@ public:
> 
>   SSL *ssl;
>   ink_hrtime sslHandshakeBeginTime;
> +  ink_hrtime sslLastWriteTime;
> +  int64_t    sslTotalBytesSent;
> 
>   static int advertise_next_protocol(SSL * ssl, const unsigned char ** out, 
> unsigned * outlen, void *);
>   static int select_next_protocol(SSL * ssl, const unsigned char ** out, 
> unsigned char * outlen, const unsigned char * in, unsigned inlen, void *);
> 
> http://git-wip-us.apache.org/repos/asf/trafficserver/blob/dee36e71/iocore/net/P_SSLUtils.h
> ----------------------------------------------------------------------
> diff --git a/iocore/net/P_SSLUtils.h b/iocore/net/P_SSLUtils.h
> index ec7b0b9..3b77e7d 100644
> --- a/iocore/net/P_SSLUtils.h
> +++ b/iocore/net/P_SSLUtils.h
> @@ -70,6 +70,8 @@ enum SSL_Stats
>   ssl_total_tickets_verified_stat,
>   ssl_total_tickets_not_found_stat,
>   ssl_total_tickets_renewed_stat,
> +  ssl_total_dyn_def_tls_record_count,
> +  ssl_total_dyn_max_tls_record_count,
>   ssl_session_cache_hit,
>   ssl_session_cache_miss,
>   ssl_session_cache_eviction,
> 
> http://git-wip-us.apache.org/repos/asf/trafficserver/blob/dee36e71/iocore/net/SSLNetVConnection.cc
> ----------------------------------------------------------------------
> diff --git a/iocore/net/SSLNetVConnection.cc b/iocore/net/SSLNetVConnection.cc
> index ba6f435..01d9eae 100644
> --- a/iocore/net/SSLNetVConnection.cc
> +++ b/iocore/net/SSLNetVConnection.cc
> @@ -617,12 +617,26 @@ SSLNetVConnection::load_buffer_and_write(int64_t 
> towrite, int64_t &wattempted, i
>   ProxyMutex *mutex = this_ethread()->mutex;
>   int64_t r = 0;
>   int64_t l = 0;
> +  uint32_t dynamic_tls_record_size = 0;
>   ssl_error_t err = SSL_ERROR_NONE;
> 
>   // XXX Rather than dealing with the block directly, we should use the 
> IOBufferReader API.
>   int64_t offset = buf.reader()->start_offset;
>   IOBufferBlock *b = buf.reader()->block;
> 
> +  // Dynamic TLS record sizing
> +  ink_hrtime now = 0;
> +  if (SSLConfigParams::ssl_maxrecord == -1) {
> +    now = ink_get_hrtime_internal();
> +    int msec_since_last_write = ink_hrtime_to_msec(now - sslLastWriteTime);

ink_hrtime_diff_msec

> +
> +    if (msec_since_last_write > SSL_DEF_TLS_RECORD_MSEC_THRESHOLD) {
> +      // reset sslTotalBytesSent upon inactivity for 
> SSL_DEF_TLS_RECORD_MSEC_THRESHOLD
> +      sslTotalBytesSent = 0;
> +    }
> +    Debug("ssl", "SSLNetVConnection::loadBufferAndCallWrite, now %" PRId64 
> ",lastwrite %" PRId64 " ,msec_since_last_write %d", now, sslLastWriteTime, 
> msec_since_last_write);
> +  }
> +
>   if (HttpProxyPort::TRANSPORT_BLIND_TUNNEL == this->attributes) {
>     return this->super::load_buffer_and_write(towrite, wattempted, 
> total_wrote, buf, needs);

This is not your change, but s/total_wrote/total_written/ ;)

>   }
> @@ -648,7 +662,25 @@ SSLNetVConnection::load_buffer_and_write(int64_t 
> towrite, int64_t &wattempted, i
>     // operations.
>     int64_t orig_l = l;
>     if (SSLConfigParams::ssl_maxrecord > 0 && l > 
> SSLConfigParams::ssl_maxrecord) {
> -        l = SSLConfigParams::ssl_maxrecord;
> +      l = SSLConfigParams::ssl_maxrecord;
> +
> +      // if ssl_maxrecord is configured higher than SSL_MAX_TLS_RECORD_SIZE
> +      // round off the SSL_write at multiples of SSL_MAX_TLS_RECORD_SIZE to
> +      // ensure openSSL can flush at TLS record boundary
> +      if (l > SSL_MAX_TLS_RECORD_SIZE) {
> +         l -= (l % SSL_MAX_TLS_RECORD_SIZE);
> +      }

AFAICT, this is not necessary. The SSL transport will fragment at record 
boundaries. This code just confuses the reader.

> +    } else if (SSLConfigParams::ssl_maxrecord == -1) {
> +      if (sslTotalBytesSent < SSL_DEF_TLS_RECORD_BYTE_THRESHOLD) {
> +        dynamic_tls_record_size = SSL_DEF_TLS_RECORD_SIZE;
> +        SSL_INCREMENT_DYN_STAT(ssl_total_dyn_def_tls_record_count);
> +      } else {
> +        dynamic_tls_record_size = SSL_MAX_TLS_RECORD_SIZE;
> +        SSL_INCREMENT_DYN_STAT(ssl_total_dyn_max_tls_record_count);
> +      }
> +      if (l > dynamic_tls_record_size) {
> +        l = dynamic_tls_record_size;
> +      }
>     }
> 
>     if (!l) {
> @@ -660,6 +692,7 @@ SSLNetVConnection::load_buffer_and_write(int64_t towrite, 
> int64_t &wattempted, i
>     Debug("ssl", "SSLNetVConnection::loadBufferAndCallWrite, before 
> SSLWriteBuffer, l=%" PRId64", towrite=%" PRId64", b=%p",
>           l, towrite, b);
>     err = SSLWriteBuffer(ssl, b->start() + offset, l, r);
> +
>     if (r == l) {
>       wattempted = total_wrote;
>     }
> @@ -676,6 +709,8 @@ SSLNetVConnection::load_buffer_and_write(int64_t towrite, 
> int64_t &wattempted, i
>   } while (r == l && total_wrote < towrite && b);
> 
>   if (r > 0) {
> +    sslLastWriteTime = now;
> +    sslTotalBytesSent += total_wrote;
>     if (total_wrote != wattempted) {
>       Debug("ssl", "SSLNetVConnection::loadBufferAndCallWrite, wrote some 
> bytes, but not all requested.");
>       // I'm not sure how this could happen. We should have tried and hit an 
> EAGAIN.
> @@ -744,6 +779,8 @@ SSLNetVConnection::SSLNetVConnection():
>   npnSet(NULL),
>   npnEndpoint(NULL)
> {
> +  sslLastWriteTime = 0;
> +  sslTotalBytesSent = 0;

Why isn't this in the initializer list?

You also should reset these in SSLNetVConnection::free. I expect the handshake 
stat is wrong too, since that is not reset either.

> }
> 
> void
> @@ -936,6 +973,8 @@ SSLNetVConnection::sslServerHandShakeEvent(int &err)
>     }
> 
>     sslHandShakeComplete = true;
> +    sslLastWriteTime = 0;
> +    sslTotalBytesSent = 0;

This is weird, are you compensating for the missing code in free()?

> 
>     if (sslHandshakeBeginTime) {
>       const ink_hrtime ssl_handshake_time = ink_get_hrtime() - 
> sslHandshakeBeginTime;
> @@ -1058,6 +1097,8 @@ SSLNetVConnection::sslClientHandShakeEvent(int &err)
>     }
> 
>     sslHandShakeComplete = true;
> +    sslLastWriteTime = 0;
> +    sslTotalBytesSent = 0;

This too

>     return EVENT_DONE;
> 
>   case SSL_ERROR_WANT_WRITE:
> 
> http://git-wip-us.apache.org/repos/asf/trafficserver/blob/dee36e71/iocore/net/SSLUtils.cc
> ----------------------------------------------------------------------
> diff --git a/iocore/net/SSLUtils.cc b/iocore/net/SSLUtils.cc
> index 27e0c19..286ba69 100644
> --- a/iocore/net/SSLUtils.cc
> +++ b/iocore/net/SSLUtils.cc
> @@ -1794,6 +1794,10 @@ SSLWriteBuffer(SSL * ssl, const void * buf, int64_t 
> nbytes, int64_t& nwritten)
>   int ret = SSL_write(ssl, buf, (int)nbytes);
>   if (ret > 0) {
>     nwritten = ret;
> +    BIO *bio = SSL_get_wbio(ssl);
> +    if (bio != NULL) {
> +      BIO_flush(bio);
> +    }
>     return SSL_ERROR_NONE;
>   }
> 
> 

Reply via email to