/* SPDX-License-Identifier: Apache-2.0
 * Copyright(c) 2022 Cisco Systems, Inc.
 */

/**
 * @file
 * @brief SR Path Tracing (PT)
 *
 * SR PT CLI
 *
 */

#include <vlib/vlib.h>
#include <vnet/vnet.h>
#include <vnet/srv6/sr.h>
#include <vnet/ip/ip.h>
#include <vnet/srv6/sr_packet.h>
#include <vnet/ip/ip6_packet.h>
#include <vnet/fib/ip6_fib.h>
#include <vnet/dpo/dpo.h>
#include <vnet/adj/adj.h>
#include <vnet/srv6/sr_pt.h>

#include <vppinfra/error.h>
#include <vppinfra/elog.h>

sr_pt_main_t sr_pt_main;

void *
sr_pt_find_iface (u32 iface)
{
  sr_pt_main_t *sr_pt = &sr_pt_main;
  uword *p;

  /* Search for the item */
  p = mhash_get (&sr_pt->sr_pt_iface_index_hash, &iface);
  if (p)
    {
      /* Retrieve sr_pt_iface */
      return pool_elt_at_index (sr_pt->sr_pt_iface, p[0]);
    }
  return NULL;
}

int
sr_pt_add_iface (u32 iface, u16 id, u8 ingress_load, u8 egress_load,
		 u8 tts_template)
{
  sr_pt_main_t *sr_pt = &sr_pt_main;
  uword *p;

  sr_pt_iface_t *ls = 0;

  if (iface == (u32) ~0)
    return SR_PT_ERR_IFACE_INVALID;

  /* Search for the item */
  p = mhash_get (&sr_pt->sr_pt_iface_index_hash, &iface);

  if (p)
    return SR_PT_ERR_EXIST;

  if (id > SR_PT_ID_MAX)
    return SR_PT_ERR_ID_INVALID;

  if (ingress_load > SR_PT_LOAD_MAX || egress_load > SR_PT_LOAD_MAX)
    return SR_PT_ERR_LOAD_INVALID;

  if (tts_template > SR_PT_TTS_TEMPLATE_MAX)
    return SR_PT_ERR_TTS_TEMPLATE_INVALID;

  /* Create a new sr_pt_iface */
  pool_get_zero (sr_pt->sr_pt_iface, ls);
  ls->iface = iface;
  ls->id = id;
  ls->ingress_load = ingress_load;
  ls->egress_load = egress_load;
  ls->tts_template = tts_template;

  /* Set hash key for searching sr_pt_iface by iface */
  mhash_set (&sr_pt->sr_pt_iface_index_hash, &iface, ls - sr_pt->sr_pt_iface,
	     NULL);
  return 0;
}

int
sr_pt_del_iface (u32 iface)
{
  sr_pt_main_t *sr_pt = &sr_pt_main;
  uword *p;

  sr_pt_iface_t *ls = 0;

  if (iface == (u32) ~0)
    return SR_PT_ERR_IFACE_INVALID;

  /* Search for the item */
  p = mhash_get (&sr_pt->sr_pt_iface_index_hash, &iface);

  if (p)
    {
      /* Retrieve sr_pt_iface */
      ls = pool_elt_at_index (sr_pt->sr_pt_iface, p[0]);
      /* Delete sr_pt_iface */
      pool_put (sr_pt->sr_pt_iface, ls);
      mhash_unset (&sr_pt->sr_pt_iface_index_hash, &iface, NULL);
    }
  else
    {
      return SR_PT_ERR_NOENT;
    }
  return 0;
}

/**
 * @brief "sr pt add iface" CLI function.
 *
 * @see sr_pt_add_iface
 */
static clib_error_t *
sr_pt_add_iface_command_fn (vlib_main_t *vm, unformat_input_t *input,
			    vlib_cli_command_t *cmd)
{
  vnet_main_t *vnm = vnet_get_main ();
  u32 iface = (u32) ~0;
  u32 id = (u32) ~0;
  u32 ingress_load = 0;
  u32 egress_load = 0;
  u32 tts_template = SR_PT_TTS_TEMPLATE_DEFAULT;

  int rv;

  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
    {
      if (unformat (input, "%U", unformat_vnet_sw_interface, vnm, &iface))
	;
      else if (unformat (input, "id %u", &id))
	;
      else if (unformat (input, "ingress-load %u", &ingress_load))
	;
      else if (unformat (input, "egress-load %u", &egress_load))
	;
      else if (unformat (input, "tts-template %u", &tts_template))
	;
      else
	break;
    }

  rv = sr_pt_add_iface (iface, id, ingress_load, egress_load, tts_template);

  switch (rv)
    {
    case 0:
      break;
    case SR_PT_ERR_EXIST:
      return clib_error_return (0, "Error: Identical iface already exists.");
    case SR_PT_ERR_IFACE_INVALID:
      return clib_error_return (0, "Error: The iface name invalid.");
    case SR_PT_ERR_ID_INVALID:
      return clib_error_return (0, "Error: The iface id value invalid.");
    case SR_PT_ERR_LOAD_INVALID:
      return clib_error_return (
	0, "Error: The iface ingress or egress load value invalid.");
    case SR_PT_ERR_TTS_TEMPLATE_INVALID:
      return clib_error_return (
	0, "Error: The iface TTS Template value invalid.");
    default:
      return clib_error_return (0, "Error: unknown error.");
    }
  return 0;
}

/**
 * @brief "sr pt del iface" CLI function.
 *
 * @see sr_pt_del_iface
 */
static clib_error_t *
sr_pt_del_iface_command_fn (vlib_main_t *vm, unformat_input_t *input,
			    vlib_cli_command_t *cmd)
{
  vnet_main_t *vnm = vnet_get_main ();
  u32 iface = (u32) ~0;

  int rv;

  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
    {
      if (unformat (input, "%U", unformat_vnet_sw_interface, vnm, &iface))
	;
      else
	break;
    }

  rv = sr_pt_del_iface (iface);

  switch (rv)
    {
    case 0:
      break;
    case SR_PT_ERR_NOENT:
      return clib_error_return (0, "Error: No such iface.");
    case SR_PT_ERR_IFACE_INVALID:
      return clib_error_return (0, "Error: The iface name is not valid.");
    default:
      return clib_error_return (0, "Error: unknown error.");
    }
  return 0;
}

/**
 * @brief CLI function to show all SR PT interfcaes
 */
static clib_error_t *
sr_pt_show_iface_command_fn (vlib_main_t *vm, unformat_input_t *input,
			     vlib_cli_command_t *cmd)
{
  vnet_main_t *vnm = vnet_get_main ();
  sr_pt_main_t *sr_pt = &sr_pt_main;
  sr_pt_iface_t **sr_pt_iface_list = 0;
  sr_pt_iface_t *ls;
  int i;

  vlib_cli_output (vm, "SR PT Interfaces");
  vlib_cli_output (vm, "==================================");

  pool_foreach (ls, sr_pt->sr_pt_iface)
    {
      vec_add1 (sr_pt_iface_list, ls);
    };

  for (i = 0; i < vec_len (sr_pt_iface_list); i++)
    {
      ls = sr_pt_iface_list[i];
      vlib_cli_output (
	vm,
	"\tiface       : \t%U\n\tid          : \t%d\n\tingress-load: "
	"\t%d\n\tegress-load : \t%d\n\ttts-template: \t%d  ",
	format_vnet_sw_if_index_name, vnm, ls->iface, ls->id, ls->ingress_load,
	ls->egress_load, ls->tts_template);
      vlib_cli_output (vm, "--------------------------------");
    }

  return 0;
}

VLIB_CLI_COMMAND (sr_pt_add_iface_command, static) = {
  .path = "sr pt add iface",
  .short_help = "sr pt add iface <iface-name> id <pt-iface-id> ingress-load "
		"<ingress-load-value> egress-load <egress-load-value> "
		"tts-template <tts-template-value>",
  .function = sr_pt_add_iface_command_fn,
};

VLIB_CLI_COMMAND (sr_pt_del_iface_command, static) = {
  .path = "sr pt del iface",
  .short_help = "sr pt del iface <iface-name>",
  .function = sr_pt_del_iface_command_fn,
};

VLIB_CLI_COMMAND (sr_pt_show_iface_command, static) = {
  .path = "sr pt show iface",
  .short_help = "sr pt show iface",
  .function = sr_pt_show_iface_command_fn,
};

/**
 *  * @brief SR PT initialization
 *   */
clib_error_t *
sr_pt_init (vlib_main_t *vm)
{
  sr_pt_main_t *pt = &sr_pt_main;
  mhash_init (&pt->sr_pt_iface_index_hash, sizeof (uword), sizeof (u32));
  return 0;
}

VLIB_INIT_FUNCTION (sr_pt_init);