/*
 * 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.
 */
/*
 * config.c: feature configuration
 *
 * Copyright (c) 2008 Eliot Dresselhaus
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#include <vnet/vnet.h>

static vnet_config_feature_t *
duplicate_feature_vector (vnet_config_feature_t * feature_vector)
{
  vnet_config_feature_t *result, *f;

  result = vec_dup (feature_vector);
  vec_foreach (f, result) f->feature_config = vec_dup (f->feature_config);

  return result;
}

static void
free_feature_vector (vnet_config_feature_t * feature_vector)
{
  vnet_config_feature_t *f;

  vec_foreach (f, feature_vector) vnet_config_feature_free (f);
  vec_free (feature_vector);
}

static u32
add_next (vlib_main_t * vm,
	  vnet_config_main_t * cm, u32 last_node_index, u32 this_node_index)
{
  u32 i, ni = ~0;

  if (last_node_index != ~0)
    return vlib_node_add_next (vm, last_node_index, this_node_index);

  for (i = 0; i < vec_len (cm->start_node_indices); i++)
    {
      u32 tmp;
      tmp =
	vlib_node_add_next (vm, cm->start_node_indices[i], this_node_index);
      if (ni == ~0)
	ni = tmp;
      /* Start nodes to first must agree on next indices. */
      ASSERT (ni == tmp);
    }

  return ni;
}

static vnet_config_t *
find_config_with_features (vlib_main_t * vm,
			   vnet_config_main_t * cm,
			   vnet_config_feature_t * feature_vector,
			   u32 end_node_index)
{
  u32 last_node_index = ~0;
  vnet_config_feature_t *f;
  u32 *config_string;
  uword *p;
  vnet_config_t *c;

  config_string = cm->config_string_temp;
  cm->config_string_temp = 0;
  if (config_string)
    _vec_len (config_string) = 0;

  vec_foreach (f, feature_vector)
  {
    /* Connect node graph. */
    f->next_index = add_next (vm, cm, last_node_index, f->node_index);
    last_node_index = f->node_index;

    /* Store next index in config string. */
    vec_add1 (config_string, f->next_index);

    /* Store feature config. */
    vec_add (config_string, f->feature_config, vec_len (f->feature_config));
  }

  /* Terminate config string with next for end node. */
  if (last_node_index == ~0 || last_node_index != end_node_index)
    {
      u32 next_index = add_next (vm, cm, last_node_index, end_node_index);
      vec_add1 (config_string, next_index);
    }

  /* See if config string is unique. */
  p = hash_get_mem (cm->config_string_hash, config_string);
  if (p)
    {
      /* Not unique.  Share existing config. */
      cm->config_string_temp = config_string;	/* we'll use it again later. */
      free_feature_vector (feature_vector);
      c = pool_elt_at_index (cm->config_pool, p[0]);
    }
  else
    {
      u32 *d;

      pool_get (cm->config_pool, c);
      c->index = c - cm->config_pool;
      c->features = feature_vector;
      c->config_string_vector = config_string;

      /* Allocate copy of config string in heap.
         VLIB buffers will maintain pointers to heap as they read out
         configuration data. */
      c->config_string_heap_index
	= heap_alloc (cm->config_string_heap, vec_len (config_string) + 1,
		      c->config_string_heap_handle);

      /* First element in heap points back to pool index. */
      d =
	vec_elt_at_index (cm->config_string_heap,
			  c->config_string_heap_index);
      d[0] = c->index;
      clib_memcpy (d + 1, config_string, vec_bytes (config_string));
      hash_set_mem (cm->config_string_hash, config_string, c->index);

      c->reference_count = 0;	/* will be incremented by caller. */

      vec_validate_init_empty (cm->end_node_indices_by_user_index,
			       c->config_string_heap_index + 1,
			       cm->default_end_node_index);
      cm->end_node_indices_by_user_index[c->config_string_heap_index + 1]
	= end_node_index;
    }

  return c;
}

void
vnet_config_init (vlib_main_t * vm,
		  vnet_config_main_t * cm,
		  char *start_node_names[],
		  int n_start_node_names,
		  char *feature_node_names[], int n_feature_node_names)
{
  vlib_node_t *n;
  u32 i;

  clib_memset (cm, 0, sizeof (cm[0]));

  cm->config_string_hash =
    hash_create_vec (0,
		     STRUCT_SIZE_OF (vnet_config_t, config_string_vector[0]),
		     sizeof (uword));

  ASSERT (n_feature_node_names >= 1);

  vec_resize (cm->start_node_indices, n_start_node_names);
  for (i = 0; i < n_start_node_names; i++)
    {
      n = vlib_get_node_by_name (vm, (u8 *) start_node_names[i]);
      /* Given node name must exist. */
      ASSERT (n != 0);
      cm->start_node_indices[i] = n->index;
    }

  vec_resize (cm->node_index_by_feature_index, n_feature_node_names);
  for (i = 0; i < n_feature_node_names; i++)
    {
      if (!feature_node_names[i])
	cm->node_index_by_feature_index[i] = ~0;
      else
	{
	  n = vlib_get_node_by_name (vm, (u8 *) feature_node_names[i]);
	  /* Given node may exist in plug-in library which is not present */
	  if (n)
	    {
	      if (i + 1 == n_feature_node_names)
		cm->default_end_node_index = n->index;
	      cm->node_index_by_feature_index[i] = n->index;
	    }
	  else
	    cm->node_index_by_feature_index[i] = ~0;
	}
    }
}

static void
remove_reference (vnet_config_main_t * cm, vnet_config_t * c)
{
  ASSERT (c->reference_count > 0);
  c->reference_count -= 1;
  if (c->reference_count == 0)
    {
      hash_unset (cm->config_string_hash, c->config_string_vector);
      vnet_config_free (cm, c);
      pool_put (cm->config_pool, c);
    }
}

static int
feature_cmp (void *a1, void *a2)
{
  vnet_config_feature_t *f1 = a1;
  vnet_config_feature_t *f2 = a2;

  return (int) f1->feature_index - f2->feature_index;
}

always_inline u32 *
vnet_get_config_heap (vnet_config_main_t * cm, u32 ci)
{
  return heap_elt_at_index (cm->config_string_heap, ci);
}

void
vnet_config_del (vnet_config_main_t * cm, u32 config_id)
{
  u32 *p = vnet_get_config_heap (cm, config_id);
  vnet_config_t *old = pool_elt_at_index (cm->config_pool, p[-1]);
  remove_reference (cm, old);
}

u32
vnet_config_modify_end_node (vlib_main_t * vm,
			     vnet_config_main_t * cm,
			     u32 config_string_heap_index, u32 end_node_index)
{
  vnet_config_feature_t *new_features;
  vnet_config_t *old, *new;

  if (end_node_index == ~0)	// feature node does not exist
    return ~0;

  if (config_string_heap_index == ~0)
    {
      old = 0;
      new_features = 0;
    }
  else
    {
      u32 *p = vnet_get_config_heap (cm, config_string_heap_index);
      old = pool_elt_at_index (cm->config_pool, p[-1]);
      new_features = old->features;
      if (new_features)
	new_features = duplicate_feature_vector (new_features);
    }

  if (vec_len (new_features))
    {
      /* is the last feature the cuurent end node */
      u32 last = vec_len (new_features) - 1;
      if (new_features[last].node_index == cm->default_end_node_index)
	{
	  vec_free (new_features->feature_config);
	  _vec_len (new_features) = last;
	}
    }

  if (old)
    remove_reference (cm, old);

  new = find_config_with_features (vm, cm, new_features, end_node_index);
  new->reference_count += 1;

  /*
   * User gets pointer to config string first element
   * (which defines the pool index
   * this config string comes from).
   */
  vec_validate (cm->config_pool_index_by_user_index,
		new->config_string_heap_index + 1);
  cm->config_pool_index_by_user_index[new->config_string_heap_index + 1]
    = new - cm->config_pool;
  return new->config_string_heap_index + 1;
}

u32
vnet_config_add_feature (vlib_main_t * vm,
			 vnet_config_main_t * cm,
			 u32 config_string_heap_index,
			 u32 feature_index,
			 void *feature_config, u32 n_feature_config_bytes)
{
  vnet_config_t *old, *new;
  vnet_config_feature_t *new_features, *f;
  u32 n_feature_config_u32s, end_node_index;
  u32 node_index = vec_elt (cm->node_index_by_feature_index, feature_index);

  if (node_index == ~0)		// feature node does not exist
    return ~0;

  if (config_string_heap_index == ~0)
    {
      old = 0;
      new_features = 0;
      end_node_index = cm->default_end_node_index;
    }
  else
    {
      u32 *p = vnet_get_config_heap (cm, config_string_heap_index);
      old = pool_elt_at_index (cm->config_pool, p[-1]);
      new_features = old->features;
      end_node_index =
	cm->end_node_indices_by_user_index[config_string_heap_index];
      if (new_features)
	new_features = duplicate_feature_vector (new_features);
    }

  vec_add2 (new_features, f, 1);
  f->feature_index = feature_index;
  f->node_index = node_index;

  if (n_feature_config_bytes)
    {
      n_feature_config_u32s =
	round_pow2 (n_feature_config_bytes,
		    sizeof (f->feature_config[0])) /
	sizeof (f->feature_config[0]);
      vec_validate (f->feature_config, n_feature_config_u32s - 1);
      clib_memcpy_fast (f->feature_config, feature_config,
			n_feature_config_bytes);
    }

  /* Sort (prioritize) features. */
  if (vec_len (new_features) > 1)
    vec_sort_with_function (new_features, feature_cmp);

  if (old)
    remove_reference (cm, old);

  new = find_config_with_features (vm, cm, new_features, end_node_index);
  new->reference_count += 1;

  /*
   * User gets pointer to config string first element
   * (which defines the pool index
   * this config string comes from).
   */
  vec_validate (cm->config_pool_index_by_user_index,
		new->config_string_heap_index + 1);
  cm->config_pool_index_by_user_index[new->config_string_heap_index + 1]
    = new - cm->config_pool;
  return new->config_string_heap_index + 1;
}

u32
vnet_config_del_feature (vlib_main_t * vm,
			 vnet_config_main_t * cm,
			 u32 config_string_heap_index,
			 u32 feature_index,
			 void *feature_config, u32 n_feature_config_bytes)
{
  vnet_config_t *old, *new;
  vnet_config_feature_t *new_features, *f;
  u32 n_feature_config_u32s;

  {
    u32 *p = vnet_get_config_heap (cm, config_string_heap_index);

    old = pool_elt_at_index (cm->config_pool, p[-1]);
  }

  n_feature_config_u32s =
    round_pow2 (n_feature_config_bytes,
		sizeof (f->feature_config[0])) /
    sizeof (f->feature_config[0]);

  /* Find feature with same index and opaque data. */
  vec_foreach (f, old->features)
  {
    if (f->feature_index == feature_index
	&& vec_len (f->feature_config) == n_feature_config_u32s
	&& (n_feature_config_u32s == 0
	    || !memcmp (f->feature_config, feature_config,
			n_feature_config_bytes)))
      break;
  }

  /* Feature not found. */
  if (f >= vec_end (old->features))
    return ~0;

  new_features = duplicate_feature_vector (old->features);
  f = new_features + (f - old->features);
  vnet_config_feature_free (f);
  vec_delete (new_features, 1, f - new_features);

  /* must remove old from config_pool now as it may be expanded and change
     memory location if the following function find_config_with_features()
     adds a new config because none of existing config's has matching features
     and so can be reused */
  remove_reference (cm, old);
  new = find_config_with_features (vm, cm, new_features,
				   cm->end_node_indices_by_user_index
				   [config_string_heap_index]);
  new->reference_count += 1;

  vec_validate (cm->config_pool_index_by_user_index,
		new->config_string_heap_index + 1);
  cm->config_pool_index_by_user_index[new->config_string_heap_index + 1]
    = new - cm->config_pool;
  return new->config_string_heap_index + 1;
}

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