/*
 * Copyright (c) 2015 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.
 */

#include <vnet/ipsec/ipsec.h>
#include <vnet/ipsec/ipsec_io.h>

int
ipsec_add_del_spd (vlib_main_t * vm, u32 spd_id, int is_add)
{
  ipsec_main_t *im = &ipsec_main;
  ipsec_spd_t *spd = 0;
  ipsec_spd_fp_t *fp_spd = 0;
  uword *p;
  u32 spd_index, k, v;

  p = hash_get (im->spd_index_by_spd_id, spd_id);
  if (p && is_add)
    return VNET_API_ERROR_ENTRY_ALREADY_EXISTS;
  if (!p && !is_add)
    return VNET_API_ERROR_NO_SUCH_ENTRY;

  if (!is_add)			/* delete */
    {
      spd_index = p[0];
      spd = pool_elt_at_index (im->spds, spd_index);
      if (!spd)
	return VNET_API_ERROR_INVALID_VALUE;

      /* *INDENT-OFF* */
      hash_foreach (k, v, im->spd_index_by_sw_if_index, ({
        if (v == spd_index)
          ipsec_set_interface_spd(vm, k, spd_id, 0);
      }));
      /* *INDENT-ON* */
      hash_unset (im->spd_index_by_spd_id, spd_id);
#define _(s,v) vec_free(spd->policies[IPSEC_SPD_POLICY_##s]);
      foreach_ipsec_spd_policy_type
#undef _

	fp_spd = &spd->fp_spd;

      if (im->fp_spd_ipv4_out_is_enabled)
	{
	  if (fp_spd->ip4_out_lookup_hash_idx != INDEX_INVALID)
	    {
	      clib_bihash_16_8_t *bihash_table =
		pool_elt_at_index (im->fp_ip4_lookup_hashes_pool,
				   fp_spd->ip4_out_lookup_hash_idx);

	      clib_bihash_free_16_8 (bihash_table);
	      vec_free (fp_spd->name4_out);
	      pool_put_index (im->fp_ip4_lookup_hashes_pool,
			      fp_spd->ip4_out_lookup_hash_idx);
	    }
	}

      if (im->fp_spd_ipv4_in_is_enabled)
	{
	  if (fp_spd->ip4_in_lookup_hash_idx != INDEX_INVALID)
	    {
	      clib_bihash_16_8_t *bihash_table = pool_elt_at_index (
		im->fp_ip4_lookup_hashes_pool, fp_spd->ip4_in_lookup_hash_idx);

	      clib_bihash_free_16_8 (bihash_table);
	      vec_free (fp_spd->name4_in);
	      pool_put_index (im->fp_ip4_lookup_hashes_pool,
			      fp_spd->ip4_in_lookup_hash_idx);
	    }
	}

      if (im->fp_spd_ipv6_out_is_enabled)
	{
	  if (fp_spd->ip6_out_lookup_hash_idx != INDEX_INVALID)
	    {
	      clib_bihash_40_8_t *bihash_table =
		pool_elt_at_index (im->fp_ip6_lookup_hashes_pool,
				   fp_spd->ip6_out_lookup_hash_idx);

	      clib_bihash_free_40_8 (bihash_table);
	      vec_free (fp_spd->name6_out);
	      pool_put_index (im->fp_ip6_lookup_hashes_pool,
			      fp_spd->ip6_out_lookup_hash_idx);
	    }
	}
      if (im->fp_spd_ipv6_in_is_enabled)
	{
	  if (fp_spd->ip6_in_lookup_hash_idx != INDEX_INVALID)
	    {
	      clib_bihash_40_8_t *bihash_table = pool_elt_at_index (
		im->fp_ip6_lookup_hashes_pool, fp_spd->ip6_in_lookup_hash_idx);

	      clib_bihash_free_40_8 (bihash_table);
	      vec_free (fp_spd->name6_in);
	      pool_put_index (im->fp_ip6_lookup_hashes_pool,
			      fp_spd->ip6_in_lookup_hash_idx);
	    }
	}

      pool_put (im->spds, spd);
    }
  else /* create new SPD */
    {
      pool_get (im->spds, spd);
      clib_memset (spd, 0, sizeof (*spd));
      spd_index = spd - im->spds;
      spd->id = spd_id;
      hash_set (im->spd_index_by_spd_id, spd_id, spd_index);

      fp_spd = &spd->fp_spd;
      fp_spd->ip4_out_lookup_hash_idx = INDEX_INVALID;
      fp_spd->ip4_in_lookup_hash_idx = INDEX_INVALID;
      fp_spd->ip6_out_lookup_hash_idx = INDEX_INVALID;
      fp_spd->ip6_in_lookup_hash_idx = INDEX_INVALID;

      if (im->fp_spd_ipv4_out_is_enabled)
	{
	  if (pool_elts (im->fp_ip4_lookup_hashes_pool) <
	      pool_max_len (im->fp_ip4_lookup_hashes_pool))
	    {
	      clib_bihash_16_8_t *bihash_table;
	      fp_spd->name4_out = format (0, "spd_%u_fp_ip4_out", spd_id);

	      pool_get (im->fp_ip4_lookup_hashes_pool, bihash_table);
	      fp_spd->ip4_out_lookup_hash_idx =
		bihash_table - im->fp_ip4_lookup_hashes_pool;
	      clib_bihash_init_16_8 (bihash_table, (char *) fp_spd->name4_out,
				     im->fp_lookup_hash_buckets,
				     im->fp_lookup_hash_buckets *
				       IPSEC_FP_IP4_HASH_MEM_PER_BUCKET);
	    }
	}

      if (im->fp_spd_ipv4_in_is_enabled)
	{
	  if (pool_elts (im->fp_ip4_lookup_hashes_pool) <
	      pool_max_len (im->fp_ip4_lookup_hashes_pool))
	    {
	      clib_bihash_16_8_t *bihash_table;
	      fp_spd->name4_in = format (0, "spd_%u_fp_ip4_in", spd_id);

	      pool_get (im->fp_ip4_lookup_hashes_pool, bihash_table);
	      fp_spd->ip4_in_lookup_hash_idx =
		bihash_table - im->fp_ip4_lookup_hashes_pool;
	      clib_bihash_init_16_8 (bihash_table, (char *) fp_spd->name4_in,
				     im->fp_lookup_hash_buckets,
				     im->fp_lookup_hash_buckets *
				       IPSEC_FP_IP4_HASH_MEM_PER_BUCKET);
	    }
	}
      if (im->fp_spd_ipv6_out_is_enabled)
	{
	  if (pool_elts (im->fp_ip6_lookup_hashes_pool) <
	      pool_max_len (im->fp_ip6_lookup_hashes_pool))
	    {
	      clib_bihash_40_8_t *bihash_table;
	      ipsec_spd_fp_t *fp_spd = &spd->fp_spd;

	      fp_spd->name6_out = format (0, "spd_%u_fp_ip6_out", spd_id);

	      fp_spd->name6_out = format (0, "spd_%u_fp_ip6_out", spd_id);
	      pool_get (im->fp_ip6_lookup_hashes_pool, bihash_table);
	      fp_spd->ip6_out_lookup_hash_idx =
		bihash_table - im->fp_ip6_lookup_hashes_pool;
	      clib_bihash_init_40_8 (bihash_table, (char *) fp_spd->name6_out,
				     im->fp_lookup_hash_buckets,
				     im->fp_lookup_hash_buckets *
				       IPSEC_FP_IP6_HASH_MEM_PER_BUCKET);
	    }
	}
      if (im->fp_spd_ipv6_in_is_enabled)
	{
	  if (pool_elts (im->fp_ip6_lookup_hashes_pool) <
	      pool_max_len (im->fp_ip6_lookup_hashes_pool))
	    {
	      clib_bihash_40_8_t *bihash_table;
	      ipsec_spd_fp_t *fp_spd = &spd->fp_spd;

	      fp_spd->name6_in = format (0, "spd_%u_fp_ip6_in", spd_id);
	      pool_get (im->fp_ip6_lookup_hashes_pool, bihash_table);
	      fp_spd->ip6_in_lookup_hash_idx =
		bihash_table - im->fp_ip6_lookup_hashes_pool;
	      clib_bihash_init_40_8 (bihash_table, (char *) fp_spd->name6_in,
				     im->fp_lookup_hash_buckets,
				     im->fp_lookup_hash_buckets *
				       IPSEC_FP_IP6_HASH_MEM_PER_BUCKET);
	    }
	}
    }
  return 0;
}

int
ipsec_set_interface_spd (vlib_main_t * vm, u32 sw_if_index, u32 spd_id,
			 int is_add)
{
  ipsec_main_t *im = &ipsec_main;
  ip4_ipsec_config_t config;

  u32 spd_index;
  uword *p;

  p = hash_get (im->spd_index_by_spd_id, spd_id);
  if (!p)
    return VNET_API_ERROR_SYSCALL_ERROR_1;	/* no such spd-id */

  spd_index = p[0];

  p = hash_get (im->spd_index_by_sw_if_index, sw_if_index);
  if (p && is_add)
    return VNET_API_ERROR_SYSCALL_ERROR_2;	/* spd already assigned */

  if (is_add)
    {
      hash_set (im->spd_index_by_sw_if_index, sw_if_index, spd_index);
    }
  else
    {
      hash_unset (im->spd_index_by_sw_if_index, sw_if_index);
    }

  /* enable IPsec on TX */
  vnet_feature_enable_disable ("ip4-output", "ipsec4-output-feature",
			       sw_if_index, is_add, 0, 0);
  vnet_feature_enable_disable ("ip6-output", "ipsec6-output-feature",
			       sw_if_index, is_add, 0, 0);

  config.spd_index = spd_index;

  /* enable IPsec on RX */
  vnet_feature_enable_disable ("ip4-unicast", "ipsec4-input-feature",
			       sw_if_index, is_add, &config, sizeof (config));
  vnet_feature_enable_disable ("ip6-unicast", "ipsec6-input-feature",
			       sw_if_index, is_add, &config, sizeof (config));

  return 0;
}

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