/* 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 if (unformat (input, "args %U", unformat_single_quoted_string,
			 &args->args))
	;
      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, "args %U", unformat_single_quoted_string,
			 &args.args))
	;
      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);
      vec_free (args.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 (!err && 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);
	}
      else if (unformat (&input, "dev %U", unformat_c_string_array, device_id,
			 sizeof (device_id)))
	{
	  unformat_input_t no_input = {};
	  unformat_init_vector (&no_input, 0);
	  err = vnet_dev_config_one_device (vm, &no_input, device_id);
	  unformat_free (&no_input);
	}
      else
	err = clib_error_return (0, "unknown input '%U'",
				 format_unformat_error, &input);
    }

  unformat_free (&input);

  if (err)
    {
      log_err (0, "%U", format_clib_error, err);
      clib_error_free (err);
    }

  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");
