/*
 * Copyright (c) 2016 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/feature/feature.h>
#include <vnet/classify/flow_classify.h>

flow_classify_main_t flow_classify_main;

static void
vnet_flow_classify_feature_enable (vlib_main_t * vnm,
				   flow_classify_main_t * fcm,
				   u32 sw_if_index,
				   flow_classify_table_id_t tid,
				   int feature_enable)
{
  vnet_feature_config_main_t *vfcm;
  u8 arc;

  if (tid == FLOW_CLASSIFY_TABLE_IP4)
    {
      vnet_feature_enable_disable ("ip4-unicast", "ip4-flow-classify",
				   sw_if_index, feature_enable, 0, 0);
      arc = vnet_get_feature_arc_index ("ip4-unicast");
    }
  else
    {
      vnet_feature_enable_disable ("ip6-unicast", "ip6-flow-classify",
				   sw_if_index, feature_enable, 0, 0);
      arc = vnet_get_feature_arc_index ("ip6-unicast");
    }

  vfcm = vnet_get_feature_arc_config_main (arc);
  fcm->vnet_config_main[tid] = &vfcm->config_main;
}

int
vnet_set_flow_classify_intfc (vlib_main_t * vm, u32 sw_if_index,
			      u32 ip4_table_index, u32 ip6_table_index,
			      u32 is_add)
{
  flow_classify_main_t *fcm = &flow_classify_main;
  vnet_classify_main_t *vcm = fcm->vnet_classify_main;
  u32 pct[FLOW_CLASSIFY_N_TABLES] = { ip4_table_index, ip6_table_index };
  u32 ti;

  /* Assume that we've validated sw_if_index in the API layer */

  for (ti = 0; ti < FLOW_CLASSIFY_N_TABLES; ti++)
    {
      if (pct[ti] == ~0)
	continue;

      if (pool_is_free_index (vcm->tables, pct[ti]))
	return VNET_API_ERROR_NO_SUCH_TABLE;

      vec_validate_init_empty
	(fcm->classify_table_index_by_sw_if_index[ti], sw_if_index, ~0);

      /* Reject any DEL operation with wrong sw_if_index */
      if (!is_add &&
	  (pct[ti] !=
	   fcm->classify_table_index_by_sw_if_index[ti][sw_if_index]))
	{
	  clib_warning
	    ("Non-existent intf_idx=%d with table_index=%d for delete",
	     sw_if_index, pct[ti]);
	  return VNET_API_ERROR_NO_SUCH_TABLE;
	}

      /* Return ok on ADD operaton if feature is already enabled */
      if (is_add &&
	  fcm->classify_table_index_by_sw_if_index[ti][sw_if_index] != ~0)
	return 0;

      vnet_flow_classify_feature_enable (vm, fcm, sw_if_index, ti, is_add);

      if (is_add)
	fcm->classify_table_index_by_sw_if_index[ti][sw_if_index] = pct[ti];
      else
	fcm->classify_table_index_by_sw_if_index[ti][sw_if_index] = ~0;
    }


  return 0;
}

static clib_error_t *
set_flow_classify_command_fn (vlib_main_t * vm,
			      unformat_input_t * input,
			      vlib_cli_command_t * cmd)
{
  vnet_main_t *vnm = vnet_get_main ();
  u32 sw_if_index = ~0;
  u32 ip4_table_index = ~0;
  u32 ip6_table_index = ~0;
  u32 is_add = 1;
  u32 idx_cnt = 0;
  int rv;

  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
    {
      if (unformat (input, "interface %U", unformat_vnet_sw_interface,
		    vnm, &sw_if_index))
	;
      else if (unformat (input, "ip4-table %d", &ip4_table_index))
	idx_cnt++;
      else if (unformat (input, "ip6-table %d", &ip6_table_index))
	idx_cnt++;
      else if (unformat (input, "del"))
	is_add = 0;
      else
	break;
    }

  if (sw_if_index == ~0)
    return clib_error_return (0, "Interface must be specified.");

  if (!idx_cnt)
    return clib_error_return (0, "Table index should be specified.");

  if (idx_cnt > 1)
    return clib_error_return (0, "Only one table index per API is allowed.");

  rv = vnet_set_flow_classify_intfc (vm, sw_if_index, ip4_table_index,
				     ip6_table_index, is_add);

  switch (rv)
    {
    case 0:
      break;

    case VNET_API_ERROR_NO_MATCHING_INTERFACE:
      return clib_error_return (0, "No such interface");

    case VNET_API_ERROR_NO_SUCH_ENTRY:
      return clib_error_return (0, "No such classifier table");
    }
  return 0;
}

/* *INDENT-OFF* */
VLIB_CLI_COMMAND (set_input_acl_command, static) = {
    .path = "set flow classify",
    .short_help =
    "set flow classify interface <int> [ip4-table <index>]\n"
    "  [ip6-table <index>] [del]",
    .function = set_flow_classify_command_fn,
};
/* *INDENT-ON* */

static uword
unformat_table_type (unformat_input_t * input, va_list * va)
{
  u32 *r = va_arg (*va, u32 *);
  u32 tid;

  if (unformat (input, "ip4"))
    tid = FLOW_CLASSIFY_TABLE_IP4;
  else if (unformat (input, "ip6"))
    tid = FLOW_CLASSIFY_TABLE_IP6;
  else
    return 0;

  *r = tid;
  return 1;
}

static clib_error_t *
show_flow_classify_command_fn (vlib_main_t * vm,
			       unformat_input_t * input,
			       vlib_cli_command_t * cmd)
{
  flow_classify_main_t *fcm = &flow_classify_main;
  u32 type = FLOW_CLASSIFY_N_TABLES;
  u32 *vec_tbl;
  int i;

  if (unformat (input, "type %U", unformat_table_type, &type))
    ;
  else
    return clib_error_return (0, "Type must be specified.");;

  if (type == FLOW_CLASSIFY_N_TABLES)
    return clib_error_return (0, "Invalid table type.");

  vec_tbl = fcm->classify_table_index_by_sw_if_index[type];

  if (vec_len (vec_tbl))
    vlib_cli_output (vm, "%10s%20s\t\t%s", "Intfc idx", "Classify table",
		     "Interface name");
  else
    vlib_cli_output (vm, "No tables configured.");

  for (i = 0; i < vec_len (vec_tbl); i++)
    {
      if (vec_elt (vec_tbl, i) == ~0)
	continue;

      vlib_cli_output (vm, "%10d%20d\t\t%U", i, vec_elt (vec_tbl, i),
		       format_vnet_sw_if_index_name, fcm->vnet_main, i);
    }

  return 0;
}

/* *INDENT-OFF* */
VLIB_CLI_COMMAND (show_flow_classify_command, static) = {
    .path = "show classify flow",
    .short_help = "show classify flow type [ip4|ip6]",
    .function = show_flow_classify_command_fn,
};
/* *INDENT-ON* */

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