/*
 * Copyright (c) 2017-2019 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 <vppinfra/error.h>

u8 RT (rule_is_exact_match) (RTT (mma_rule) * key, RTT (mma_rule) * r)
{
  int i;

  for (i = 0; i < ARRAY_LEN (key->match.as_u64); i++)
    {
      if (key->match.as_u64[i] != r->match.as_u64[i])
	return 0;
    }
  for (i = 0; i < ARRAY_LEN (key->mask.as_u64); i++)
    {
      if (key->mask.as_u64[i] != r->mask.as_u64[i])
	return 0;
    }
  return 1;
}

u8
RT (rule_is_match_for_key) (RTT (mma_mask_or_match) * key, RTT (mma_rule) * r)
{
  RTT (mma_mask_or_match) _tmp_key, *tkp = &_tmp_key;
  int i;

  *tkp = *key;
  for (i = 0; i < ARRAY_LEN (tkp->as_u64); i++)
    tkp->as_u64[i] &= r->mask.as_u64[i];
  for (i = 0; i < ARRAY_LEN (tkp->as_u64); i++)
    {
      if (tkp->as_u64[i] != r->match.as_u64[i])
	return 0;
    }
  return 1;
}

RTT (mma_rule) * RT (mma_rules_table_rule_alloc) (RTT (mma_rules_table) * srt)
{
  RTT (mma_rule) * rule;
  pool_get (srt->rules, rule);
  clib_memset (rule, 0, sizeof (*rule));
  return rule;
}

RTT (mma_rule) *
RT (mma_rule_free) (RTT (mma_rules_table) * srt, RTT (mma_rule) * rule)
{
  clib_memset (rule, 0xfa, sizeof (*rule));
  pool_put (srt->rules, rule);
  return rule;
}

void RT (mma_rules_table_free) (RTT (mma_rules_table) * srt)
{
  RTT (mma_rule) * rule;

  pool_flush (rule, srt->rules, ({}));
  pool_free (srt->rules);
}

RTT (mma_rule) *
RT (mma_rules_table_get_rule) (RTT (mma_rules_table) * srt, u32 srt_index)
{
  if (!pool_is_free_index (srt->rules, srt_index))
    return (srt->rules + srt_index);
  return 0;
}

u32
RT (mma_rules_table_rule_index) (RTT (mma_rules_table) * srt,
				 RTT (mma_rule) * sr)
{
  ASSERT (sr);
  return (sr - srt->rules);
}

/**
 * Lookup key in table
 *
 * This should be optimized .. eventually
 */
u32
RT (mma_rules_table_lookup) (RTT (mma_rules_table) * srt,
			     RTT (mma_mask_or_match) * key, u32 rule_index)
{
  RTT (mma_rule) * rp;
  u32 rv;
  int i;

  ASSERT (rule_index != MMA_TABLE_INVALID_INDEX);
  rp = RT (mma_rules_table_get_rule) (srt, rule_index);
  ASSERT (rp);

  if (!RT (rule_is_match_for_key) (key, rp))
    return MMA_TABLE_INVALID_INDEX;
  for (i = 0; i < vec_len (rp->next_indices); i++)
    {
      rv = RT (mma_rules_table_lookup) (srt, key, rp->next_indices[i]);
      if (rv != MMA_TABLE_INVALID_INDEX)
	return (rv);
    }
  return (rp->action_index);
}

u32
RT (mma_rules_table_lookup_rule) (RTT (mma_rules_table) * srt,
				  RTT (mma_mask_or_match) * key,
				  u32 rule_index)
{
  RTT (mma_rule) * rp;
  u32 rv;
  int i;

  ASSERT (rule_index != MMA_TABLE_INVALID_INDEX);
  rp = RT (mma_rules_table_get_rule) (srt, rule_index);
  ASSERT (rp);

  if (!RT (rule_is_match_for_key) (key, rp))
    return MMA_TABLE_INVALID_INDEX;
  for (i = 0; i < vec_len (rp->next_indices); i++)
    {
      rv = RT (mma_rules_table_lookup_rule) (srt, key, rp->next_indices[i]);
      if (rv != MMA_TABLE_INVALID_INDEX)
	return (rv);
    }
  return rule_index;
}

static
RTT (mma_rules_table) *
RTT (sort_srt);

     int RT (mma_sort_indices) (void *e1, void *e2)
{
  u32 *ri1 = e1, *ri2 = e2;
  RTT (mma_rule) * rule1, *rule2;
  rule1 = RT (mma_rules_table_get_rule) (RTT (sort_srt), *ri1);
  rule2 = RT (mma_rules_table_get_rule) (RTT (sort_srt), *ri2);
  return RTT (sort_srt)->rule_cmp_fn (rule1, rule2);
}

void RT (mma_sort) (RTT (mma_rules_table) * srt, u32 * next_indices)
{
  RTT (sort_srt) = srt;
  vec_sort_with_function (next_indices, RT (mma_sort_indices));
}

int
RT (mma_rules_table_add_rule) (RTT (mma_rules_table) * srt,
			       RTT (mma_rule) * rule)
{
  u32 parent_index, i, *next_indices = 0, added = 0, rule_index;
  RTT (mma_rule) * parent, *child;

  rule_index = RT (mma_rules_table_rule_index) (srt, rule);
  parent_index = RT (mma_rules_table_lookup_rule) (srt, &rule->match,
						   srt->root_index);
  parent = RT (mma_rules_table_get_rule) (srt, parent_index);
  if (RT (rule_is_exact_match) (rule, parent))
    {
      parent->action_index = rule->action_index;
      RT (mma_rule_free) (srt, rule);
      return -1;
    }

  if (vec_len (parent->next_indices) == 0)
    {
      vec_add1 (parent->next_indices, rule_index);
      return 0;
    }

  /* Check if new rule is parent of some of the existing children */
  for (i = 0; i < vec_len (parent->next_indices); i++)
    {
      child = RT (mma_rules_table_get_rule) (srt, parent->next_indices[i]);
      if (RT (rule_is_match_for_key) (&child->match, rule))
	{
	  vec_add1 (rule->next_indices, parent->next_indices[i]);
	  if (!added)
	    {
	      vec_add1 (next_indices, rule_index);
	      added = 1;
	    }
	}
      else
	{
	  if (!added && srt->rule_cmp_fn (rule, child) < 0)
	    {
	      vec_add1 (next_indices, rule_index);
	      added = 1;
	    }
	  vec_add1 (next_indices, parent->next_indices[i]);
	}
    }
  if (!added)
    vec_add1 (next_indices, rule_index);
  vec_free (parent->next_indices);
  parent->next_indices = next_indices;
  return 0;
}

int
RT (mma_rules_table_del_rule) (RTT (mma_rules_table) * srt,
			       RTT (mma_rule) * rule, u32 rule_index)
{
  RTT (mma_rule) * rp;
  u32 rv;
  int i;

  ASSERT (rule_index != MMA_TABLE_INVALID_INDEX);
  rp = RT (mma_rules_table_get_rule) (srt, rule_index);

  if (!RT (rule_is_match_for_key) (&rule->match, rp))
    return MMA_TABLE_INVALID_INDEX;
  if (RT (rule_is_exact_match) (rule, rp))
    {
      if (rule_index == srt->root_index)
	rp->action_index = MMA_TABLE_INVALID_INDEX;
      return 1;
    }
  for (i = 0; i < vec_len (rp->next_indices); i++)
    {
      rv = RT (mma_rules_table_del_rule) (srt, rule, rp->next_indices[i]);
      if (rv == 1)
	{
	  RTT (mma_rule) * child;
	  u32 *next_indices = 0, *new_elts, left_to_add;
	  child = RT (mma_rules_table_get_rule) (srt, rp->next_indices[i]);
	  ASSERT (RT (rule_is_exact_match) (rule, child));

	  if (i != 0)
	    {
	      vec_add2 (next_indices, new_elts, i);
	      clib_memcpy_fast (new_elts, rp->next_indices, i * sizeof (u32));
	    }
	  if (vec_len (child->next_indices))
	    vec_append (next_indices, child->next_indices);
	  left_to_add = vec_len (rp->next_indices) - i - 1;
	  if (left_to_add)
	    {
	      vec_add2 (next_indices, new_elts, left_to_add);
	      clib_memcpy_fast (new_elts, &rp->next_indices[i + 1],
				left_to_add * sizeof (u32));
	    }
	  RT (mma_rule_free) (srt, child);
	  vec_free (rp->next_indices);
	  rp->next_indices = next_indices;
	  return 0;
	}
      else if (rv == 0)
	return rv;
    }
  return MMA_TABLE_INVALID_INDEX;
}

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