summaryrefslogtreecommitdiffstats
path: root/src/vnet/tls/tls.c
diff options
context:
space:
mode:
authorFlorin Coras <fcoras@cisco.com>2022-02-24 16:35:26 -0800
committerDave Barach <openvpp@barachs.net>2022-02-28 21:04:14 +0000
commit8c5e5f64023146a20e1a9e774b76d6bf713b622b (patch)
tree363cbbbe69a1032475911b2ad7c1ca2c213ae968 /src/vnet/tls/tls.c
parent3683d1b5ab253c90506231c1590d92ae95454ee4 (diff)
tls: handle read write ssl errors
Type: improvement Signed-off-by: Florin Coras <fcoras@cisco.com> Change-Id: If5eed7dac4951f0510a4b4b092f66f44d0d3cacd
Diffstat (limited to 'src/vnet/tls/tls.c')
-rw-r--r--src/vnet/tls/tls.c10
1 files changed, 10 insertions, 0 deletions
diff --git a/src/vnet/tls/tls.c b/src/vnet/tls/tls.c
index b91282ce074..54bb739e11d 100644
--- a/src/vnet/tls/tls.c
+++ b/src/vnet/tls/tls.c
@@ -400,6 +400,16 @@ tls_ctx_handshake_is_over (tls_ctx_t * ctx)
}
void
+tls_notify_app_io_error (tls_ctx_t *ctx)
+{
+ ASSERT (tls_ctx_handshake_is_over (ctx));
+
+ session_transport_reset_notify (&ctx->connection);
+ session_transport_closed_notify (&ctx->connection);
+ tls_disconnect_transport (ctx);
+}
+
+void
tls_session_reset_callback (session_t * s)
{
tls_ctx_t *ctx;
'n182' href='#n182'>182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269
/*
 * Copyright (c) 2018 Cisco and/or its affiliates.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at:
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/**
 * @file
 * @brief NAT plugin client-IP based session affinity for load-balancing
 */

#include <nat/nat_affinity.h>
#include <nat/nat.h>

nat_affinity_main_t nat_affinity_main;

#define AFFINITY_HASH_BUCKETS 65536
#define AFFINITY_HASH_MEMORY (2 << 25)

u8 *
format_affinity_kvp (u8 * s, va_list * args)
{
  clib_bihash_kv_16_8_t *v = va_arg (*args, clib_bihash_kv_16_8_t *);
  nat_affinity_key_t k;

  k.as_u64[0] = v->key[0];
  k.as_u64[1] = v->key[1];

  s = format (s, "client %U backend %U:%d proto %U index %llu",
	      format_ip4_address, &k.client_addr,
	      format_ip4_address, &k.service_addr,
	      clib_net_to_host_u16 (k.service_port),
	      format_snat_protocol, k.proto);

  return s;
}

clib_error_t *
nat_affinity_init (vlib_main_t * vm)
{
  nat_affinity_main_t *nam = &nat_affinity_main;
  vlib_thread_main_t *tm = vlib_get_thread_main ();
  clib_error_t *error = 0;

  if (tm->n_vlib_mains > 1)
    clib_spinlock_init (&nam->affinity_lock);

  clib_bihash_init_16_8 (&nam->affinity_hash, "nat-affinity",
			 AFFINITY_HASH_BUCKETS, AFFINITY_HASH_MEMORY);
  clib_bihash_set_kvp_format_fn_16_8 (&nam->affinity_hash,
				      format_affinity_kvp);

  nam->vlib_main = vm;

  return error;
}

static_always_inline void
make_affinity_kv (clib_bihash_kv_16_8_t * kv, ip4_address_t client_addr,
		  ip4_address_t service_addr, u8 proto, u16 service_port)
{
  nat_affinity_key_t *key = (nat_affinity_key_t *) kv->key;

  key->client_addr = client_addr;
  key->service_addr = service_addr;
  key->proto = proto;
  key->service_port = service_port;

  kv->value = ~0ULL;
}

u32
nat_affinity_get_per_service_list_head_index (void)
{
  nat_affinity_main_t *nam = &nat_affinity_main;
  dlist_elt_t *head_elt;

  clib_spinlock_lock_if_init (&nam->affinity_lock);

  pool_get (nam->list_pool, head_elt);
  clib_dlist_init (nam->list_pool, head_elt - nam->list_pool);

  clib_spinlock_unlock_if_init (&nam->affinity_lock);

  return head_elt - nam->list_pool;
}

void
nat_affinity_flush_service (u32 affinity_per_service_list_head_index)
{
  nat_affinity_main_t *nam = &nat_affinity_main;
  u32 elt_index;
  dlist_elt_t *elt;
  nat_affinity_t *a;
  clib_bihash_kv_16_8_t kv;

  clib_spinlock_lock_if_init (&nam->affinity_lock);

  while ((elt_index =
	  clib_dlist_remove_head (nam->list_pool,
				  affinity_per_service_list_head_index)) !=
	 ~0)
    {
      elt = pool_elt_at_index (nam->list_pool, elt_index);
      a = pool_elt_at_index (nam->affinity_pool, elt->value);
      kv.key[0] = a->key.as_u64[0];
      kv.key[1] = a->key.as_u64[1];
      pool_put_index (nam->affinity_pool, elt->value);
      if (clib_bihash_add_del_16_8 (&nam->affinity_hash, &kv, 0))
	nat_elog_warn ("affinity key del failed");
      pool_put_index (nam->list_pool, elt_index);
    }
  pool_put_index (nam->list_pool, affinity_per_service_list_head_index);

  clib_spinlock_unlock_if_init (&nam->affinity_lock);
}

int
nat_affinity_find_and_lock (ip4_address_t client_addr,
			    ip4_address_t service_addr, u8 proto,
			    u16 service_port, u8 * backend_index)
{
  nat_affinity_main_t *nam = &nat_affinity_main;
  clib_bihash_kv_16_8_t kv, value;
  nat_affinity_t *a;
  int rv = 0;

  make_affinity_kv (&kv, client_addr, service_addr, proto, service_port);
  clib_spinlock_lock_if_init (&nam->affinity_lock);
  if (clib_bihash_search_16_8 (&nam->affinity_hash, &kv, &value))
    {
      rv = 1;
      goto unlock;
    }

  a = pool_elt_at_index (nam->affinity_pool, value.value);
  /* if already expired delete */
  if (a->ref_cnt == 0)
    {
      if (a->expire < vlib_time_now (nam->vlib_main))
	{
	  clib_dlist_remove (nam->list_pool, a->per_service_index);
	  pool_put_index (nam->list_pool, a->per_service_index);
	  pool_put_index (nam->affinity_pool, value.value);
	  if (clib_bihash_add_del_16_8 (&nam->affinity_hash, &kv, 0))
	    nat_elog_warn ("affinity key del failed");
	  rv = 1;
	  goto unlock;
	}
    }
  a->ref_cnt++;
  *backend_index = a->backend_index;

unlock:
  clib_spinlock_unlock_if_init (&nam->affinity_lock);
  return rv;
}

static int
affinity_is_expired_cb (clib_bihash_kv_16_8_t * kv, void *arg)
{
  nat_affinity_main_t *nam = &nat_affinity_main;
  nat_affinity_t *a;

  a = pool_elt_at_index (nam->affinity_pool, kv->value);
  if (a->ref_cnt == 0)
    {
      if (a->expire < vlib_time_now (nam->vlib_main))
	{
	  clib_dlist_remove (nam->list_pool, a->per_service_index);
	  pool_put_index (nam->list_pool, a->per_service_index);
	  pool_put_index (nam->affinity_pool, kv->value);
	  if (clib_bihash_add_del_16_8 (&nam->affinity_hash, kv, 0))
	    nat_elog_warn ("affinity key del failed");
	  return 1;
	}
    }

  return 0;
}

int
nat_affinity_create_and_lock (ip4_address_t client_addr,
			      ip4_address_t service_addr, u8 proto,
			      u16 service_port, u8 backend_index,
			      u32 sticky_time,
			      u32 affinity_per_service_list_head_index)
{
  nat_affinity_main_t *nam = &nat_affinity_main;
  clib_bihash_kv_16_8_t kv, value;
  nat_affinity_t *a;
  dlist_elt_t *list_elt;
  int rv = 0;

  make_affinity_kv (&kv, client_addr, service_addr, proto, service_port);
  clib_spinlock_lock_if_init (&nam->affinity_lock);
  if (!clib_bihash_search_16_8 (&nam->affinity_hash, &kv, &value))
    {
      rv = 1;
      nat_elog_notice ("affinity key already exist");
      goto unlock;
    }

  pool_get (nam->affinity_pool, a);
  kv.value = a - nam->affinity_pool;
  rv =
    clib_bihash_add_or_overwrite_stale_16_8 (&nam->affinity_hash, &kv,
					     affinity_is_expired_cb, NULL);
  if (rv)
    {
      nat_elog_notice ("affinity key add failed");
      pool_put (nam->affinity_pool, a);
      goto unlock;
    }

  pool_get (nam->list_pool, list_elt);
  clib_dlist_init (nam->list_pool, list_elt - nam->list_pool);
  list_elt->value = a - nam->affinity_pool;
  a->per_service_index = list_elt - nam->list_pool;
  a->backend_index = backend_index;
  a->ref_cnt = 1;
  a->sticky_time = sticky_time;
  a->key.as_u64[0] = kv.key[0];
  a->key.as_u64[1] = kv.key[1];
  clib_dlist_addtail (nam->list_pool, affinity_per_service_list_head_index,
		      a->per_service_index);

unlock:
  clib_spinlock_unlock_if_init (&nam->affinity_lock);
  return rv;
}

void
nat_affinity_unlock (ip4_address_t client_addr, ip4_address_t service_addr,
		     u8 proto, u16 service_port)
{
  nat_affinity_main_t *nam = &nat_affinity_main;
  clib_bihash_kv_16_8_t kv, value;
  nat_affinity_t *a;

  make_affinity_kv (&kv, client_addr, service_addr, proto, service_port);
  clib_spinlock_lock_if_init (&nam->affinity_lock);
  if (clib_bihash_search_16_8 (&nam->affinity_hash, &kv, &value))
    goto unlock;

  a = pool_elt_at_index (nam->affinity_pool, value.value);
  a->ref_cnt--;
  if (a->ref_cnt == 0)
    a->expire = (u64) a->sticky_time + vlib_time_now (nam->vlib_main);

unlock:
  clib_spinlock_unlock_if_init (&nam->affinity_lock);
}

/*
 * fd.io coding-style-patch-verification: ON
 *
 * Local Variables:
 * eval: (c-set-style "gnu")
 * End:
 */