vcl session: refactor passing of crypto context

Pass tls/quic crypto context using extended config instead of bloating
conect/listen messages.

Type: refactor

Signed-off-by: Florin Coras <fcoras@cisco.com>
Change-Id: I0bc637ae310e6c31ef1e16847501dcb81453ee94
diff --git a/src/plugins/hs_apps/echo_client.c b/src/plugins/hs_apps/echo_client.c
index 4680ae2..d641a9e 100644
--- a/src/plugins/hs_apps/echo_client.c
+++ b/src/plugins/hs_apps/echo_client.c
@@ -718,6 +718,13 @@
   return 0;
 }
 
+static int
+echo_client_transport_needs_crypto (transport_proto_t proto)
+{
+  return proto == TRANSPORT_PROTO_TLS || proto == TRANSPORT_PROTO_DTLS ||
+	 proto == TRANSPORT_PROTO_QUIC;
+}
+
 clib_error_t *
 echo_clients_connect (vlib_main_t * vm, u32 n_clients)
 {
@@ -736,10 +743,18 @@
       clib_memcpy (&a->sep_ext, &sep, sizeof (sep));
       a->api_context = i;
       a->app_index = ecm->app_index;
-      a->sep_ext.ckpair_index = ecm->ckpair_index;
+      if (echo_client_transport_needs_crypto (a->sep_ext.transport_proto))
+	{
+	  session_endpoint_alloc_ext_cfg (&a->sep_ext,
+					  TRANSPORT_ENDPT_EXT_CFG_CRYPTO);
+	  a->sep_ext.ext_cfg->crypto.ckpair_index = ecm->ckpair_index;
+	}
 
       vlib_worker_thread_barrier_sync (vm);
-      if ((rv = vnet_connect (a)))
+      rv = vnet_connect (a);
+      if (a->sep_ext.ext_cfg)
+	clib_mem_free (a->sep_ext.ext_cfg);
+      if (rv)
 	{
 	  vlib_worker_thread_barrier_release (vm);
 	  return clib_error_return (0, "connect returned: %d", rv);
diff --git a/src/plugins/hs_apps/echo_server.c b/src/plugins/hs_apps/echo_server.c
index 63150d5..b75a366 100644
--- a/src/plugins/hs_apps/echo_server.c
+++ b/src/plugins/hs_apps/echo_server.c
@@ -385,6 +385,13 @@
 }
 
 static int
+echo_client_transport_needs_crypto (transport_proto_t proto)
+{
+  return proto == TRANSPORT_PROTO_TLS || proto == TRANSPORT_PROTO_DTLS ||
+	 proto == TRANSPORT_PROTO_QUIC;
+}
+
+static int
 echo_server_listen ()
 {
   i32 rv;
@@ -398,7 +405,12 @@
       return -1;
     }
   args->app_index = esm->app_index;
-  args->sep_ext.ckpair_index = esm->ckpair_index;
+  if (echo_client_transport_needs_crypto (args->sep_ext.transport_proto))
+    {
+      session_endpoint_alloc_ext_cfg (&args->sep_ext,
+				      TRANSPORT_ENDPT_EXT_CFG_CRYPTO);
+      args->sep_ext.ext_cfg->crypto.ckpair_index = esm->ckpair_index;
+    }
 
   if (args->sep_ext.transport_proto == TRANSPORT_PROTO_UDP)
     {
@@ -407,6 +419,8 @@
 
   rv = vnet_listen (args);
   esm->listener_handle = args->handle;
+  if (args->sep_ext.ext_cfg)
+    clib_mem_free (args->sep_ext.ext_cfg);
   return rv;
 }
 
diff --git a/src/plugins/hs_apps/http_server.c b/src/plugins/hs_apps/http_server.c
index 72e3f32..34892b6 100644
--- a/src/plugins/hs_apps/http_server.c
+++ b/src/plugins/hs_apps/http_server.c
@@ -760,12 +760,20 @@
 }
 
 static int
+http_transport_needs_crypto (transport_proto_t proto)
+{
+  return proto == TRANSPORT_PROTO_TLS || proto == TRANSPORT_PROTO_DTLS ||
+	 proto == TRANSPORT_PROTO_QUIC;
+}
+
+static int
 http_server_listen ()
 {
   session_endpoint_cfg_t sep = SESSION_ENDPOINT_CFG_NULL;
   http_server_main_t *hsm = &http_server_main;
   vnet_listen_args_t _a, *a = &_a;
   char *uri = "tcp://0.0.0.0/80";
+  int rv;
 
   clib_memset (a, 0, sizeof (*a));
   a->app_index = hsm->app_index;
@@ -777,9 +785,17 @@
     return -1;
 
   clib_memcpy (&a->sep_ext, &sep, sizeof (sep));
-  a->sep_ext.ckpair_index = hsm->ckpair_index;
+  if (http_transport_needs_crypto (a->sep_ext.transport_proto))
+    {
+      session_endpoint_alloc_ext_cfg (&a->sep_ext,
+				      TRANSPORT_ENDPT_EXT_CFG_CRYPTO);
+      a->sep_ext.ext_cfg->crypto.ckpair_index = hsm->ckpair_index;
+    }
 
-  return vnet_listen (a);
+  rv = vnet_listen (a);
+  if (a->sep_ext.ext_cfg)
+    clib_mem_free (a->sep_ext.ext_cfg);
+  return rv;
 }
 
 static void
diff --git a/src/plugins/hs_apps/proxy.c b/src/plugins/hs_apps/proxy.c
index 0008158..1a49a0f 100644
--- a/src/plugins/hs_apps/proxy.c
+++ b/src/plugins/hs_apps/proxy.c
@@ -42,6 +42,8 @@
   a.app_index = pa->app_index;
   clib_memcpy (&a.sep_ext, &pa->sep, sizeof (pa->sep));
   vnet_connect (&a);
+  if (a.sep_ext.ext_cfg)
+    clib_mem_free (a.sep_ext.ext_cfg);
 }
 
 static void
@@ -50,6 +52,8 @@
   if (vlib_get_thread_index () == 0)
     {
       vnet_connect (a);
+      if (a->sep_ext.ext_cfg)
+	clib_mem_free (a->sep_ext.ext_cfg);
     }
   else
     {
@@ -283,6 +287,12 @@
 }
 
 static int
+proxy_transport_needs_crypto (transport_proto_t proto)
+{
+  return proto == TRANSPORT_PROTO_TLS;
+}
+
+static int
 proxy_rx_callback (session_t * s)
 {
   proxy_main_t *pm = &proxy_main;
@@ -353,9 +363,16 @@
       clib_spinlock_unlock_if_init (&pm->sessions_lock);
 
       clib_memcpy (&a->sep_ext, &pm->client_sep, sizeof (pm->client_sep));
-      a->sep_ext.ckpair_index = pm->ckpair_index;
       a->api_context = proxy_index;
       a->app_index = pm->active_open_app_index;
+
+      if (proxy_transport_needs_crypto (a->sep.transport_proto))
+	{
+	  session_endpoint_alloc_ext_cfg (&a->sep_ext,
+					  TRANSPORT_ENDPT_EXT_CFG_CRYPTO);
+	  a->sep_ext.ext_cfg->crypto.ckpair_index = pm->ckpair_index;
+	}
+
       proxy_call_main_thread (a);
     }
 
@@ -697,13 +714,24 @@
 {
   proxy_main_t *pm = &proxy_main;
   vnet_listen_args_t _a, *a = &_a;
+  int rv;
+
   clib_memset (a, 0, sizeof (*a));
 
   a->app_index = pm->server_app_index;
   clib_memcpy (&a->sep_ext, &pm->server_sep, sizeof (pm->server_sep));
-  a->sep_ext.ckpair_index = pm->ckpair_index;
+  if (proxy_transport_needs_crypto (a->sep.transport_proto))
+    {
+      session_endpoint_alloc_ext_cfg (&a->sep_ext,
+				      TRANSPORT_ENDPT_EXT_CFG_CRYPTO);
+      a->sep_ext.ext_cfg->crypto.ckpair_index = pm->ckpair_index;
+    }
 
-  return vnet_listen (a);
+  rv = vnet_listen (a);
+  if (a->sep_ext.ext_cfg)
+    clib_mem_free (a->sep_ext.ext_cfg);
+
+  return rv;
 }
 
 static void
diff --git a/src/plugins/hs_apps/sapi/vpp_echo_bapi.c b/src/plugins/hs_apps/sapi/vpp_echo_bapi.c
index 0a0168b..7cf15eb 100644
--- a/src/plugins/hs_apps/sapi/vpp_echo_bapi.c
+++ b/src/plugins/hs_apps/sapi/vpp_echo_bapi.c
@@ -100,6 +100,31 @@
   vl_msg_api_send_shmem (em->vl_input_queue, (u8 *) & bmp);
 }
 
+static u8
+echo_transport_needs_crypto (transport_proto_t proto)
+{
+  return proto == TRANSPORT_PROTO_TLS || proto == TRANSPORT_PROTO_DTLS ||
+	 proto == TRANSPORT_PROTO_QUIC;
+}
+
+static void
+echo_msg_add_crypto_ext_config (echo_main_t *em, uword *offset)
+{
+  transport_endpt_ext_cfg_t cfg;
+  svm_fifo_chunk_t *c;
+
+  c = echo_segment_alloc_chunk (ECHO_MQ_SEG_HANDLE, 0, sizeof (cfg), offset);
+  if (!c)
+    return;
+
+  memset (&cfg, 0, sizeof (cfg));
+  cfg.type = TRANSPORT_ENDPT_EXT_CFG_CRYPTO;
+  cfg.len = sizeof (cfg);
+  cfg.crypto.ckpair_index = em->ckpair_index;
+  cfg.crypto.crypto_engine = em->crypto_engine;
+  clib_memcpy_fast (c->data, &cfg, cfg.len);
+}
+
 void
 echo_send_listen (echo_main_t * em, ip46_address_t * ip)
 {
@@ -117,8 +142,8 @@
   clib_memcpy_fast (&mp->ip, ip, sizeof (mp->ip));
   mp->port = em->uri_elts.port;
   mp->proto = em->uri_elts.transport_proto;
-  mp->ckpair_index = em->ckpair_index;
-  mp->crypto_engine = em->crypto_engine;
+  if (echo_transport_needs_crypto (mp->proto))
+    echo_msg_add_crypto_ext_config (em, &mp->ext_config);
   app_send_ctrl_evt_to_vpp (mq, app_evt);
 }
 
@@ -163,8 +188,8 @@
   mp->port = em->uri_elts.port;
   mp->proto = em->uri_elts.transport_proto;
   mp->parent_handle = a->parent_session_handle;
-  mp->ckpair_index = em->ckpair_index;
-  mp->crypto_engine = em->crypto_engine;
+  if (echo_transport_needs_crypto (mp->proto))
+    echo_msg_add_crypto_ext_config (em, &mp->ext_config);
   mp->flags = em->connect_flag;
   app_send_ctrl_evt_to_vpp (mq, app_evt);
 }
@@ -332,6 +357,34 @@
   return 0;
 }
 
+svm_fifo_chunk_t *
+echo_segment_alloc_chunk (uword segment_handle, u32 slice_index, u32 size,
+			  uword *offset)
+{
+  echo_main_t *em = &echo_main;
+  svm_fifo_chunk_t *c;
+  fifo_segment_t *fs;
+  u32 fs_index;
+
+  fs_index = echo_segment_lookup (segment_handle);
+  if (fs_index == (u32) ~0)
+    {
+      ECHO_LOG (0, "ERROR: mq segment %lx for is not attached!",
+		segment_handle);
+      return 0;
+    }
+
+  clib_spinlock_lock (&em->segment_handles_lock);
+
+  fs = fifo_segment_get_segment (&em->segment_main, fs_index);
+  c = fifo_segment_alloc_chunk_w_slice (fs, slice_index, size);
+  *offset = fifo_segment_chunk_offset (fs, c);
+
+  clib_spinlock_unlock (&em->segment_handles_lock);
+
+  return c;
+}
+
 /*
  *
  *  Binary API callbacks
diff --git a/src/plugins/hs_apps/sapi/vpp_echo_common.h b/src/plugins/hs_apps/sapi/vpp_echo_common.h
index dc5f7df..4760f3b 100644
--- a/src/plugins/hs_apps/sapi/vpp_echo_common.h
+++ b/src/plugins/hs_apps/sapi/vpp_echo_common.h
@@ -448,6 +448,9 @@
 			 uword mq_offset, uword txf_offset, echo_session_t *s);
 int echo_segment_attach_mq (uword segment_handle, uword mq_offset,
 			    u32 mq_index, svm_msg_q_t **mq);
+svm_fifo_chunk_t *echo_segment_alloc_chunk (uword segment_handle,
+					    u32 slice_index, u32 size,
+					    uword *offset);
 
 /* Binary API */
 
diff --git a/src/plugins/http_static/static_server.c b/src/plugins/http_static/static_server.c
index b354666..23860b0 100644
--- a/src/plugins/http_static/static_server.c
+++ b/src/plugins/http_static/static_server.c
@@ -1186,12 +1186,20 @@
 }
 
 static int
+http_static_transport_needs_crypto (transport_proto_t proto)
+{
+  return proto == TRANSPORT_PROTO_TLS || proto == TRANSPORT_PROTO_DTLS ||
+	 proto == TRANSPORT_PROTO_QUIC;
+}
+
+static int
 http_static_server_listen ()
 {
   http_static_server_main_t *hsm = &http_static_server_main;
   session_endpoint_cfg_t sep = SESSION_ENDPOINT_CFG_NULL;
   vnet_listen_args_t _a, *a = &_a;
   char *uri = "tcp://0.0.0.0/80";
+  int rv;
 
   clib_memset (a, 0, sizeof (*a));
   a->app_index = hsm->app_index;
@@ -1203,9 +1211,17 @@
     return -1;
 
   clib_memcpy (&a->sep_ext, &sep, sizeof (sep));
-  a->sep_ext.ckpair_index = hsm->ckpair_index;
+  if (http_static_transport_needs_crypto (a->sep_ext.transport_proto))
+    {
+      session_endpoint_alloc_ext_cfg (&a->sep_ext,
+				      TRANSPORT_ENDPT_EXT_CFG_CRYPTO);
+      a->sep_ext.ext_cfg->crypto.ckpair_index = hsm->ckpair_index;
+    }
 
-  return vnet_listen (a);
+  rv = vnet_listen (a);
+  if (a->sep_ext.ext_cfg)
+    clib_mem_free (a->sep_ext.ext_cfg);
+  return rv;
 }
 
 static void
diff --git a/src/plugins/quic/quic.c b/src/plugins/quic/quic.c
index cf4d147..cf69727 100644
--- a/src/plugins/quic/quic.c
+++ b/src/plugins/quic/quic.c
@@ -1304,6 +1304,7 @@
 quic_connect_connection (session_endpoint_cfg_t * sep)
 {
   vnet_connect_args_t _cargs, *cargs = &_cargs;
+  transport_endpt_crypto_cfg_t *ccfg;
   quic_main_t *qm = &quic_main;
   quic_ctx_t *ctx;
   app_worker_t *app_wrk;
@@ -1312,6 +1313,11 @@
   u32 thread_index = vlib_get_thread_index ();
   int error;
 
+  if (!sep->ext_cfg)
+    return -1;
+
+  ccfg = &sep->ext_cfg->crypto;
+
   clib_memset (cargs, 0, sizeof (*cargs));
   ctx_index = quic_ctx_alloc (thread_index);
   ctx = quic_ctx_get (ctx_index, thread_index);
@@ -1323,8 +1329,8 @@
   ctx->conn_state = QUIC_CONN_STATE_HANDSHAKE;
   ctx->client_opaque = sep->opaque;
   ctx->c_flags |= TRANSPORT_CONNECTION_F_NO_LOOKUP;
-  if (sep->hostname)
-    ctx->srv_hostname = format (0, "%v", sep->hostname);
+  if (ccfg->hostname[0])
+    ctx->srv_hostname = format (0, "%s", ccfg->hostname);
   else
     /*  needed by quic for crypto + determining client / server */
     ctx->srv_hostname = format (0, "%U", format_ip46_address,
@@ -1342,8 +1348,8 @@
   cargs->sep_ext.ns_index = app->ns_index;
   cargs->sep_ext.transport_flags = TRANSPORT_CFG_F_CONNECTED;
 
-  ctx->crypto_engine = sep->crypto_engine;
-  ctx->ckpair_index = sep->ckpair_index;
+  ctx->crypto_engine = ccfg->crypto_engine;
+  ctx->ckpair_index = ccfg->ckpair_index;
   if ((error = quic_acquire_crypto_context (ctx)))
     return error;
 
@@ -1435,6 +1441,7 @@
 quic_start_listen (u32 quic_listen_session_index, transport_endpoint_t * tep)
 {
   vnet_listen_args_t _bargs, *args = &_bargs;
+  transport_endpt_crypto_cfg_t *ccfg;
   quic_main_t *qm = &quic_main;
   session_handle_t udp_handle;
   session_endpoint_cfg_t *sep;
@@ -1447,6 +1454,10 @@
   int rv;
 
   sep = (session_endpoint_cfg_t *) tep;
+  if (!sep->ext_cfg)
+    return -1;
+
+  ccfg = &sep->ext_cfg->crypto;
   app_wrk = app_worker_get (sep->app_wrk_index);
   /* We need to call this because we call app_worker_init_connected in
    * quic_accept_stream, which assumes the connect segment manager exists */
@@ -1483,8 +1494,8 @@
   lctx->parent_app_id = app_wrk->app_index;
   lctx->udp_session_handle = udp_handle;
   lctx->c_s_index = quic_listen_session_index;
-  lctx->crypto_engine = sep->crypto_engine;
-  lctx->ckpair_index = sep->ckpair_index;
+  lctx->crypto_engine = ccfg->crypto_engine;
+  lctx->ckpair_index = ccfg->ckpair_index;
   if (quic_acquire_crypto_context (lctx))
     return -1;
 
diff --git a/src/vcl/vcl_private.c b/src/vcl/vcl_private.c
index 721416b..464061c 100644
--- a/src/vcl/vcl_private.c
+++ b/src/vcl/vcl_private.c
@@ -316,6 +316,21 @@
 }
 
 int
+vcl_session_alloc_ext_cfg (vcl_session_t *s,
+			   transport_endpt_ext_cfg_type_t type)
+{
+  if (s->ext_config)
+    return -1;
+
+  s->ext_config = clib_mem_alloc (sizeof (transport_endpt_ext_cfg_t));
+  clib_memset (s->ext_config, 0, sizeof (*s->ext_config));
+  s->ext_config->len = sizeof (*s->ext_config);
+  s->ext_config->type = type;
+
+  return 0;
+}
+
+int
 vcl_segment_attach (u64 segment_handle, char *name, ssvm_segment_type_t type,
 		    int fd)
 {
diff --git a/src/vcl/vcl_private.h b/src/vcl/vcl_private.h
index 1da334a..12504c5 100644
--- a/src/vcl/vcl_private.h
+++ b/src/vcl/vcl_private.h
@@ -160,7 +160,6 @@
   vppcom_epoll_t vep;
   u32 attributes;		/**< see @ref vppcom_session_attr_t */
   int libc_epfd;
-  u32 ckpair_index;
   u32 vrf;
 
   u32 sndbuf_size;		// VPP-TBD: Hack until support setsockopt(SO_SNDBUF)
@@ -389,6 +388,8 @@
   /* Debug level set to 1 to avoid debug messages while ldp is cleaning up */
   VDBG (1, "session %u [0x%llx] removed", s->session_index, s->vpp_handle);
   vcl_session_detach_fifos (s);
+  if (s->ext_config)
+    clib_mem_free (s->ext_config);
   pool_put (wrk->sessions, s);
 }
 
@@ -663,6 +664,8 @@
 
 int vcl_session_read_ready (vcl_session_t * session);
 int vcl_session_write_ready (vcl_session_t * session);
+int vcl_session_alloc_ext_cfg (vcl_session_t *s,
+			       transport_endpt_ext_cfg_type_t type);
 
 static inline vcl_worker_t *
 vcl_worker_get (u32 wrk_index)
diff --git a/src/vcl/vppcom.c b/src/vcl/vppcom.c
index 1ece9db..a0f4338 100644
--- a/src/vcl/vppcom.c
+++ b/src/vcl/vppcom.c
@@ -193,7 +193,6 @@
   clib_memcpy_fast (&mp->ip, &s->transport.lcl_ip, sizeof (mp->ip));
   mp->port = s->transport.lcl_port;
   mp->proto = s->session_type;
-  mp->ckpair_index = s->ckpair_index;
   mp->vrf = s->vrf;
   if (s->flags & VCL_SESSION_F_CONNECTED)
     mp->flags = TRANSPORT_CFG_F_CONNECTED;
@@ -228,7 +227,6 @@
   mp->port = s->transport.rmt_port;
   mp->lcl_port = s->transport.lcl_port;
   mp->proto = s->session_type;
-  mp->ckpair_index = s->ckpair_index;
   mp->vrf = s->vrf;
   if (s->flags & VCL_SESSION_F_CONNECTED)
     mp->flags |= TRANSPORT_CFG_F_CONNECTED;
@@ -1374,7 +1372,6 @@
   session->session_type = proto;
   session->session_state = VCL_STATE_CLOSED;
   session->vpp_handle = ~0;
-  session->ckpair_index = ~0;
   session->is_dgram = vcl_proto_is_dgram (proto);
 
   if (is_nonblocking)
@@ -3710,7 +3707,17 @@
 	  rv = VPPCOM_EINVAL;
 	  break;
 	}
-      session->ckpair_index = *(uint32_t *) buffer;
+      if (!session->ext_config)
+	{
+	  vcl_session_alloc_ext_cfg (session, TRANSPORT_ENDPT_EXT_CFG_CRYPTO);
+	}
+      else if (session->ext_config->type != TRANSPORT_ENDPT_EXT_CFG_CRYPTO)
+	{
+	  rv = VPPCOM_EINVAL;
+	  break;
+	}
+
+      session->ext_config->crypto.ckpair_index = *(uint32_t *) buffer;
       break;
 
     case VPPCOM_ATTR_SET_VRF:
diff --git a/src/vnet/session/application.c b/src/vnet/session/application.c
index a93e4b9..56a5141 100644
--- a/src/vnet/session/application.c
+++ b/src/vnet/session/application.c
@@ -615,7 +615,7 @@
   cfg->q_nitems = evt_q_length;
   cfg->ring_cfgs = rc;
 
-  eqs->ssvm.ssvm_size = svm_msg_q_size_to_alloc (cfg) * n_mqs + (16 << 10);
+  eqs->ssvm.ssvm_size = svm_msg_q_size_to_alloc (cfg) * n_mqs + (1 << 20);
   eqs->ssvm.name = format (0, "%s-rx-mqs-seg%c", app->name, 0);
 
   if (ssvm_server_init (&eqs->ssvm, SSVM_SEGMENT_MEMFD))
diff --git a/src/vnet/session/application_interface.c b/src/vnet/session/application_interface.c
index a6d1a02..74f456a 100644
--- a/src/vnet/session/application_interface.c
+++ b/src/vnet/session/application_interface.c
@@ -51,15 +51,6 @@
       sep->is_ip4 = 1;
       return 1;
     }
-  else if (unformat (input, "%U://[%s]%U/%d", unformat_transport_proto,
-		     &transport_proto, &sep->hostname, unformat_ip4_address,
-		     &sep->ip.ip4, &port))
-    {
-      sep->transport_proto = transport_proto;
-      sep->port = clib_host_to_net_u16 (port);
-      sep->is_ip4 = 1;
-      return 1;
-    }
   else if (unformat (input, "%U://%U/%d", unformat_transport_proto,
 		     &transport_proto, unformat_ip6_address, &sep->ip.ip6,
 		     &port))
@@ -69,15 +60,6 @@
       sep->is_ip4 = 0;
       return 1;
     }
-  else if (unformat (input, "%U://[%s]%U/%d", unformat_transport_proto,
-		     &transport_proto, &sep->hostname, unformat_ip6_address,
-		     &sep->ip.ip6, &port))
-    {
-      sep->transport_proto = transport_proto;
-      sep->port = clib_host_to_net_u16 (port);
-      sep->is_ip4 = 0;
-      return 1;
-    }
   else if (unformat (input, "%U://session/%lu", unformat_transport_proto,
 		     &transport_proto, &sep->parent_handle))
     {
diff --git a/src/vnet/session/application_interface.h b/src/vnet/session/application_interface.h
index be6c74c..ba148e2 100644
--- a/src/vnet/session/application_interface.h
+++ b/src/vnet/session/application_interface.h
@@ -314,8 +314,6 @@
   u8 proto;
   u8 is_ip4;
   ip46_address_t ip;
-  u32 ckpair_index;
-  u8 crypto_engine;
   u8 flags;
   uword ext_config;
 } __clib_packed session_listen_msg_t;
@@ -399,18 +397,7 @@
   u32 ckpair_index;
   u8 crypto_engine;
   u8 flags;
-  union
-  {
-    struct
-    {
-      u8 hostname[16];
-      u8 hostname_len;
-    } __clib_packed;
-    struct
-    {
-      uword ext_config;
-    } __clib_packed;
-  };
+  uword ext_config;
 } __clib_packed session_connect_msg_t;
 
 STATIC_ASSERT (sizeof (session_connect_msg_t) <= SESSION_CTRL_MSG_MAX_SIZE,
@@ -870,6 +857,20 @@
   };
 } __clib_packed app_sapi_msg_t;
 
+static inline void
+session_endpoint_alloc_ext_cfg (session_endpoint_cfg_t *sep_ext,
+				transport_endpt_ext_cfg_type_t type)
+{
+  transport_endpt_ext_cfg_t *cfg;
+  u32 cfg_size;
+
+  cfg_size = sizeof (transport_endpt_ext_cfg_t);
+  cfg = clib_mem_alloc (cfg_size);
+  clib_memset (cfg, 0, cfg_size);
+  cfg->type = type;
+  sep_ext->ext_cfg = cfg;
+}
+
 #endif /* __included_uri_h__ */
 
 /*
diff --git a/src/vnet/session/session_node.c b/src/vnet/session/session_node.c
index a4db023..93ed7b7 100644
--- a/src/vnet/session/session_node.c
+++ b/src/vnet/session/session_node.c
@@ -78,8 +78,6 @@
   a->sep.fib_index = mp->vrf;
   a->sep.sw_if_index = ENDPOINT_INVALID_INDEX;
   a->sep.transport_proto = mp->proto;
-  a->sep_ext.ckpair_index = mp->ckpair_index;
-  a->sep_ext.crypto_engine = mp->crypto_engine;
   a->app_index = app->app_index;
   a->wrk_map_index = mp->wrk_index;
   a->sep_ext.transport_flags = mp->flags;
@@ -151,14 +149,7 @@
   a->sep.peer.port = mp->lcl_port;
   a->sep.peer.sw_if_index = ENDPOINT_INVALID_INDEX;
   a->sep_ext.parent_handle = mp->parent_handle;
-  a->sep_ext.ckpair_index = mp->ckpair_index;
-  a->sep_ext.crypto_engine = mp->crypto_engine;
   a->sep_ext.transport_flags = mp->flags;
-  if (mp->hostname_len)
-    {
-      vec_validate (a->sep_ext.hostname, mp->hostname_len - 1);
-      clib_memcpy_fast (a->sep_ext.hostname, mp->hostname, mp->hostname_len);
-    }
   a->api_context = mp->context;
   a->app_index = app->app_index;
   a->wrk_map_index = mp->wrk_index;
@@ -175,8 +166,6 @@
 
   if (mp->ext_config)
     session_mq_free_ext_config (app, mp->ext_config);
-
-  vec_free (a->sep_ext.hostname);
 }
 
 static void
diff --git a/src/vnet/session/session_types.h b/src/vnet/session/session_types.h
index 148f100..9211df9 100644
--- a/src/vnet/session/session_types.h
+++ b/src/vnet/session/session_types.h
@@ -44,10 +44,7 @@
   u32 opaque;
   u32 ns_index;
   u8 original_tp;
-  u8 *hostname;
   u64 parent_handle;
-  u32 ckpair_index;
-  u8 crypto_engine;
   u8 flags;
   transport_endpt_ext_cfg_t *ext_cfg;
 } session_endpoint_cfg_t;
@@ -83,8 +80,8 @@
     .fib_index = ENDPOINT_INVALID_INDEX, .is_ip4 = 0, .port = 0,              \
     .peer = TRANSPORT_ENDPOINT_NULL, .transport_proto = 0,                    \
     .app_wrk_index = ENDPOINT_INVALID_INDEX,                                  \
-    .opaque = ENDPOINT_INVALID_INDEX, .hostname = 0,                          \
-    .parent_handle = SESSION_INVALID_HANDLE, .ckpair_index = 0, .ext_cfg = 0, \
+    .opaque = ENDPOINT_INVALID_INDEX,                                         \
+    .parent_handle = SESSION_INVALID_HANDLE, .ext_cfg = 0,                    \
   }
 
 #define session_endpoint_to_transport(_sep) ((transport_endpoint_t *)_sep)
diff --git a/src/vnet/session/transport_types.h b/src/vnet/session/transport_types.h
index 0041adb..7ea8d5f 100644
--- a/src/vnet/session/transport_types.h
+++ b/src/vnet/session/transport_types.h
@@ -259,11 +259,28 @@
   };
 } transport_endpt_attr_t;
 
+typedef enum transport_endpt_ext_cfg_type_
+{
+  TRANSPORT_ENDPT_EXT_CFG_NONE,
+  TRANSPORT_ENDPT_EXT_CFG_CRYPTO,
+} transport_endpt_ext_cfg_type_t;
+
+typedef struct transport_endpt_crypto_cfg_
+{
+  u32 ckpair_index;
+  u8 crypto_engine;
+  u8 hostname[256]; /**< full domain len is 255 as per rfc 3986 */
+} transport_endpt_crypto_cfg_t;
+
 typedef struct transport_endpt_ext_cfg_
 {
   u16 type;
   u16 len;
-  u8 data[0];
+  union
+  {
+    transport_endpt_crypto_cfg_t crypto;
+    u8 data[0];
+  };
 } transport_endpt_ext_cfg_t;
 
 typedef clib_bihash_24_8_t transport_endpoint_table_t;
diff --git a/src/vnet/tls/tls.c b/src/vnet/tls/tls.c
index a950f14..808c151 100644
--- a/src/vnet/tls/tls.c
+++ b/src/vnet/tls/tls.c
@@ -280,8 +280,15 @@
 }
 
 static inline crypto_engine_type_t
-tls_get_engine_type (crypto_engine_type_t preferred)
+tls_get_engine_type (crypto_engine_type_t requested,
+		     crypto_engine_type_t preferred)
 {
+  if (requested != CRYPTO_ENGINE_NONE)
+    {
+      if (tls_vfts[requested].ctx_alloc)
+	return requested;
+      return CRYPTO_ENGINE_NONE;
+    }
   if (!tls_vfts[preferred].ctx_alloc)
     return tls_get_available_engine ();
   return preferred;
@@ -662,6 +669,7 @@
 tls_connect (transport_endpoint_cfg_t * tep)
 {
   vnet_connect_args_t _cargs = { {}, }, *cargs = &_cargs;
+  transport_endpt_crypto_cfg_t *ccfg;
   crypto_engine_type_t engine_type;
   session_endpoint_cfg_t *sep;
   tls_main_t *tm = &tls_main;
@@ -672,9 +680,14 @@
   int rv;
 
   sep = (session_endpoint_cfg_t *) tep;
+  if (!sep->ext_cfg)
+    return -1;
+
   app_wrk = app_worker_get (sep->app_wrk_index);
   app = application_get (app_wrk->app_index);
-  engine_type = tls_get_engine_type (app->tls_engine);
+
+  ccfg = &sep->ext_cfg->crypto;
+  engine_type = tls_get_engine_type (ccfg->crypto_engine, app->tls_engine);
   if (engine_type == CRYPTO_ENGINE_NONE)
     {
       clib_warning ("No tls engine_type available");
@@ -686,11 +699,11 @@
   ctx->parent_app_wrk_index = sep->app_wrk_index;
   ctx->parent_app_api_context = sep->opaque;
   ctx->tcp_is_ip4 = sep->is_ip4;
-  ctx->ckpair_index = sep->ckpair_index;
   ctx->tls_type = sep->transport_proto;
-  if (sep->hostname)
+  ctx->ckpair_index = ccfg->ckpair_index;
+  if (ccfg->hostname[0])
     {
-      ctx->srv_hostname = format (0, "%v", sep->hostname);
+      ctx->srv_hostname = format (0, "%s", ccfg->hostname);
       vec_terminate_c_string (ctx->srv_hostname);
     }
   tls_ctx_half_open_reader_unlock ();
@@ -725,6 +738,7 @@
 tls_start_listen (u32 app_listener_index, transport_endpoint_t * tep)
 {
   vnet_listen_args_t _bargs, *args = &_bargs;
+  transport_endpt_crypto_cfg_t *ccfg;
   app_worker_t *app_wrk;
   tls_main_t *tm = &tls_main;
   session_handle_t tls_al_handle;
@@ -738,9 +752,14 @@
   u32 lctx_index;
 
   sep = (session_endpoint_cfg_t *) tep;
+  if (!sep->ext_cfg)
+    return -1;
+
   app_wrk = app_worker_get (sep->app_wrk_index);
   app = application_get (app_wrk->app_index);
-  engine_type = tls_get_engine_type (app->tls_engine);
+
+  ccfg = &sep->ext_cfg->crypto;
+  engine_type = tls_get_engine_type (ccfg->crypto_engine, app->tls_engine);
   if (engine_type == CRYPTO_ENGINE_NONE)
     {
       clib_warning ("No tls engine_type available");
@@ -774,8 +793,8 @@
   lctx->app_session_handle = listen_session_get_handle (app_listener);
   lctx->tcp_is_ip4 = sep->is_ip4;
   lctx->tls_ctx_engine = engine_type;
-  lctx->ckpair_index = sep->ckpair_index;
   lctx->tls_type = sep->transport_proto;
+  lctx->ckpair_index = ccfg->ckpair_index;
 
   if (tls_vfts[engine_type].ctx_start_listen (lctx))
     {
@@ -1076,6 +1095,7 @@
 dtls_connect (transport_endpoint_cfg_t *tep)
 {
   vnet_connect_args_t _cargs = { {}, }, *cargs = &_cargs;
+  transport_endpt_crypto_cfg_t *ccfg;
   crypto_engine_type_t engine_type;
   session_endpoint_cfg_t *sep;
   tls_main_t *tm = &tls_main;
@@ -1086,9 +1106,14 @@
   int rv;
 
   sep = (session_endpoint_cfg_t *) tep;
+  if (!sep->ext_cfg)
+    return -1;
+
   app_wrk = app_worker_get (sep->app_wrk_index);
   app = application_get (app_wrk->app_index);
-  engine_type = tls_get_engine_type (app->tls_engine);
+
+  ccfg = &sep->ext_cfg->crypto;
+  engine_type = tls_get_engine_type (ccfg->crypto_engine, app->tls_engine);
   if (engine_type == CRYPTO_ENGINE_NONE)
     {
       clib_warning ("No tls engine_type available");
@@ -1100,12 +1125,12 @@
   ctx->parent_app_wrk_index = sep->app_wrk_index;
   ctx->parent_app_api_context = sep->opaque;
   ctx->tcp_is_ip4 = sep->is_ip4;
-  ctx->ckpair_index = sep->ckpair_index;
+  ctx->ckpair_index = ccfg->ckpair_index;
   ctx->tls_type = sep->transport_proto;
   ctx->tls_ctx_handle = ctx_handle;
-  if (sep->hostname)
+  if (ccfg->hostname[0])
     {
-      ctx->srv_hostname = format (0, "%v", sep->hostname);
+      ctx->srv_hostname = format (0, "%s", ccfg->hostname);
       vec_terminate_c_string (ctx->srv_hostname);
     }