/*
 * Copyright (c) 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 <vnet/teib/teib.h>

static clib_error_t *
teib_add (vlib_main_t * vm,
	  unformat_input_t * input, vlib_cli_command_t * cmd)
{
  unformat_input_t _line_input, *line_input = &_line_input;
  ip_address_t peer = ip_address_initializer;
  ip_address_t nh = ip_address_initializer;
  u32 sw_if_index, nh_table_id;
  clib_error_t *error = NULL;
  int rv;

  sw_if_index = ~0;
  nh_table_id = 0;

  /* Get a line of input. */
  if (!unformat_user (input, unformat_line_input, line_input))
    return 0;

  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
    {
      if (unformat (line_input, "%U", unformat_vnet_sw_interface,
		    vnet_get_main (), &sw_if_index))
	;
      else if (unformat (line_input, "peer %U", unformat_ip_address, &peer))
	;
      else if (unformat (line_input, "nh %U", unformat_ip_address, &nh))
	;
      else if (unformat (line_input, "nh-table-id %d", &nh_table_id))
	;
      else
	{
	  error = clib_error_return (0, "unknown input `%U'",
				     format_unformat_error, line_input);
	  goto done;
	}
    }

  if (~0 == sw_if_index)
    {
      error = clib_error_return (0, "interface required'",
				 format_unformat_error, line_input);
      goto done;
    }
  if (ip_address_is_zero (&peer))
    {
      error = clib_error_return (0, "peer required'",
				 format_unformat_error, line_input);
      goto done;
    }
  if (ip_address_is_zero (&nh))
    {
      error = clib_error_return (0, "next-hop required'",
				 format_unformat_error, line_input);
      goto done;
    }

  rv = teib_entry_add (sw_if_index, &peer, nh_table_id, &nh);

  if (rv)
    {
      error = clib_error_return_code (NULL, rv, 0,
				      "NRHP error",
				      format_unformat_error, line_input);
    }

done:
  unformat_free (line_input);

  return error;
}

/* *INDENT-OFF* */
VLIB_CLI_COMMAND (teib_create_command, static) = {
  .path = "create teib",
  .short_help = "create teib <interface> peer <addr> nh <addr> [nh-table-id <ID>]",
  .function = teib_add,
};
/* *INDENT-ON* */

static clib_error_t *
teib_del (vlib_main_t * vm,
	  unformat_input_t * input, vlib_cli_command_t * cmd)
{
  unformat_input_t _line_input, *line_input = &_line_input;
  ip_address_t peer = ip_address_initializer;
  clib_error_t *error = NULL;
  u32 sw_if_index;
  int rv;

  sw_if_index = ~0;

  /* Get a line of input. */
  if (!unformat_user (input, unformat_line_input, line_input))
    return 0;

  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
    {
      if (unformat (line_input, "%U", unformat_vnet_sw_interface,
		    vnet_get_main (), &sw_if_index))
	;
      else if (unformat (line_input, "peer %U", unformat_ip_address, &peer))
	;
      else
	{
	  error = clib_error_return (0, "unknown input `%U'",
				     format_unformat_error, line_input);
	  goto done;
	}
    }

  if (~0 == sw_if_index)
    {
      error = clib_error_return (0, "interface required'",
				 format_unformat_error, line_input);
    }
  if (ip_address_is_zero (&peer))
    {
      error = clib_error_return (0, "peer required'",
				 format_unformat_error, line_input);
      goto done;
    }

  rv = teib_entry_del (sw_if_index, &peer);

  if (rv)
    {
      error = clib_error_return_code (NULL, rv, 0,
				      "NRHP error",
				      format_unformat_error, line_input);
    }

done:
  unformat_free (line_input);

  return error;
}

/* *INDENT-OFF* */
VLIB_CLI_COMMAND (teib_delete_command, static) = {
  .path = "delete teib",
  .short_help = "delete teib <interface> peer <addr>",
  .function = teib_del,
};
/* *INDENT-ON* */

static walk_rc_t
teib_show_one (index_t nei, void *ctx)
{
  vlib_cli_output (ctx, "%U", format_teib_entry, nei);

  return (WALK_CONTINUE);
}


static clib_error_t *
teib_show (vlib_main_t * vm,
	   unformat_input_t * input, vlib_cli_command_t * cmd)
{
  teib_walk (teib_show_one, vm);
  return (NULL);
}

/* *INDENT-OFF* */
VLIB_CLI_COMMAND (teib_show_command, static) = {
  .path = "show teib",
  .short_help = "show teib",
  .function = teib_show,
};
/* *INDENT-ON* */

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