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

#include "vppinfra/error.h"
#include "vppinfra/pool.h"
#include <vnet/vnet.h>
#include <vnet/ethernet/ethernet.h>
#include <vnet/dev/dev.h>
#include <vnet/dev/api.h>
#include <vnet/dev/log.h>

VLIB_REGISTER_LOG_CLASS (dev_log, static) = {
  .class_name = "dev",
  .subclass_name = "config",
};

static clib_error_t *
vnet_dev_config_one_interface (vlib_main_t *vm, unformat_input_t *input,
			       vnet_dev_api_create_port_if_args_t *args)
{
  clib_error_t *err = 0;

  log_debug (0, "port %u %U", args->port_id, format_unformat_input, input);

  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
    {
      u32 n;

      if (unformat (input, "name %U", unformat_c_string_array, args->intf_name,
		    sizeof (args->intf_name)))
	;
      else if (unformat (input, "num-rx-queues %u", &n))
	args->num_rx_queues = n;
      else if (unformat (input, "num-tx-queues %u", &n))
	args->num_tx_queues = n;
      else if (unformat (input, "rx-queue-size %u", &n))
	args->rx_queue_size = n;
      else if (unformat (input, "tx-queue-size %u", &n))
	args->tx_queue_size = n;
      else if (unformat (input, "flags %U", unformat_vnet_dev_port_flags,
			 &args->flags))
	;
      else
	{
	  err = clib_error_return (0, "unknown input '%U'",
				   format_unformat_error, input);
	  break;
	}
    }
  return err;
}

static clib_error_t *
vnet_dev_config_one_device (vlib_main_t *vm, unformat_input_t *input,
			    char *device_id)
{
  log_debug (0, "device %s %U", device_id, format_unformat_input, input);
  clib_error_t *err = 0;
  vnet_dev_api_attach_args_t args = {};
  vnet_dev_api_create_port_if_args_t *if_args_vec = 0, *if_args;

  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
    {
      unformat_input_t sub_input;
      u32 n;

      if (unformat (input, "driver %U", unformat_c_string_array,
		    args.driver_name, sizeof (args.driver_name)))
	;
      else if (unformat (input, "flags %U", unformat_vnet_dev_flags,
			 &args.flags))
	;
      else if (unformat (input, "port %u %U", &n, unformat_vlib_cli_sub_input,
			 &sub_input))
	{
	  vnet_dev_api_create_port_if_args_t *if_args;
	  vec_add2 (if_args_vec, if_args, 1);
	  if_args->port_id = n;
	  err = vnet_dev_config_one_interface (vm, &sub_input, if_args);
	  unformat_free (&sub_input);
	  if (err)
	    break;
	}
      else
	{
	  err = clib_error_return (0, "unknown input '%U'",
				   format_unformat_error, input);
	  break;
	}
    }

  if (err == 0)
    {
      vnet_dev_rv_t rv;

      clib_memcpy (args.device_id, device_id, sizeof (args.device_id));
      rv = vnet_dev_api_attach (vm, &args);

      if (rv == VNET_DEV_OK)
	{
	  vec_foreach (if_args, if_args_vec)
	    {
	      clib_memcpy (if_args->device_id, device_id,
			   sizeof (if_args->device_id));
	      rv = vnet_dev_api_create_port_if (vm, if_args);
	      if (rv != VNET_DEV_OK)
		break;
	    }

	  if (rv != VNET_DEV_OK)
	    err = clib_error_return (0, "error: %U for device '%s'",
				     format_vnet_dev_rv, rv, device_id);
	}
    }

  vec_free (if_args_vec);
  return err;
}

uword
dev_config_process_node_fn (vlib_main_t *vm, vlib_node_runtime_t *rt,
			    vlib_frame_t *f)
{
  vnet_dev_main_t *dm = &vnet_dev_main;
  unformat_input_t input;
  clib_error_t *err = 0;

  if (dm->startup_config == 0)
    return 0;

  unformat_init_vector (&input, dm->startup_config);
  dm->startup_config = 0;

  while (unformat_check_input (&input) != UNFORMAT_END_OF_INPUT)
    {
      unformat_input_t sub_input;
      vnet_dev_device_id_t device_id;
      if (unformat (&input, "dev %U %U", unformat_c_string_array, device_id,
		    sizeof (device_id), unformat_vlib_cli_sub_input,
		    &sub_input))
	{
	  err = vnet_dev_config_one_device (vm, &sub_input, device_id);
	  unformat_free (&sub_input);
	  if (err)
	    break;
	}
      else
	{
	  err = clib_error_return (0, "unknown input '%U'",
				   format_unformat_error, input);
	  break;
	}
    }

  unformat_free (&input);

  vlib_node_set_state (vm, rt->node_index, VLIB_NODE_STATE_DISABLED);
  vlib_node_rename (vm, rt->node_index, "deleted-%u", rt->node_index);
  vec_add1 (dm->free_process_node_indices, rt->node_index);
  return 0;
}

VLIB_REGISTER_NODE (dev_config_process_node) = {
  .function = dev_config_process_node_fn,
  .type = VLIB_NODE_TYPE_PROCESS,
  .name = "dev-config",
};

static clib_error_t *
devices_config (vlib_main_t *vm, unformat_input_t *input)
{
  vnet_dev_main_t *dm = &vnet_dev_main;
  uword c;

  while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT)
    vec_add1 (dm->startup_config, c);

  return 0;
}

VLIB_CONFIG_FUNCTION (devices_config, "devices");
