/*
 * Copyright (c) 2015 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.
 */
/**
 * @file
 * @brief Host utility functions
 */
#include <vppinfra/format.h>
#include <vlib/vlib.h>

#include <vlib/threads.h>



/**
 * @brief GDB callable function: vl - Return vector length of vector
 *
 * @param *p - void - address of vector
 *
 * @return length - u32
 *
 */
u32 vl(void *p)
{
  return vec_len (p);
}

/**
 * @brief GDB callable function: pe - call pool_elts - number of elements in a pool
 *
 * @param *v - void - address of pool
 *
 * @return number - uword
 *
 */
uword pe (void *v)
{
  return (pool_elts(v));
}

/**
 * @brief GDB callable function: pifi - call pool_is_free_index - is passed index free?
 *
 * @param *p - void - address of pool
 * @param *index - u32
 *
 * @return 0|1 - int
 *
 */
int pifi (void *p, u32 index)
{
  return pool_is_free_index (p, index);
}

/**
 * @brief GDB callable function: debug_hex_bytes - return formatted hex string
 *
 * @param *s - u8
 * @param n - u32 - number of bytes to format
 *
 */
void debug_hex_bytes (u8 *s, u32 n)
{
  fformat (stderr, "%U\n", format_hex_bytes, s, n);
}

/**
 * @brief GDB callable function: vlib_dump_frame_ownership
 *
 */
void vlib_dump_frame_ownership (void)
{
  vlib_main_t * vm = vlib_get_main();
  vlib_node_main_t * nm = &vm->node_main;
  vlib_node_runtime_t * this_node_runtime;
  vlib_next_frame_t * nf;
  u32 first_nf_index;
  u32 index;

  vec_foreach(this_node_runtime, nm->nodes_by_type[VLIB_NODE_TYPE_INTERNAL])
    {
      first_nf_index = this_node_runtime->next_frame_index;

      for (index = first_nf_index; index < first_nf_index + 
             this_node_runtime->n_next_nodes; index++) 
        {
          vlib_node_runtime_t * owned_runtime;
          nf = vec_elt_at_index (vm->node_main.next_frames, index);
          if (nf->flags & VLIB_FRAME_OWNER) 
            {
              owned_runtime = vec_elt_at_index (nm->nodes_by_type[0],
                                                nf->node_runtime_index);
              fformat(stderr, 
                      "%s next index %d owns enqueue rights to %s\n",
                      nm->nodes[this_node_runtime->node_index]->name, 
                      index - first_nf_index, 
                      nm->nodes[owned_runtime->node_index]->name);
              fformat (stderr, "  nf index %d nf->frame_index %d\n",
                       nf - vm->node_main.next_frames, 
                       nf->frame_index);
            }
        }
    }
}

/**
 * @brief GDB callable function: vlib_runtime_index_to_node_name
 *
 * Takes node index and will return the node name.
 *
 * @param index - u32
 */
void vlib_runtime_index_to_node_name (u32 index)
{
  vlib_main_t * vm = vlib_get_main();
  vlib_node_main_t * nm = &vm->node_main;

  if (index > vec_len (nm->nodes))
    {
      fformat(stderr, "%d out of range, max %d\n", vec_len(nm->nodes));
      return;
    }

  fformat(stderr, "node runtime index %d name %s\n", index, nm->nodes[index]->name);
}


/**
 * @brief GDB callable function: show_gdb_command_fn - show gdb
 *
 * Shows list of functions for VPP available in GDB
 *
 * @return error - clib_error_t
 */
static clib_error_t *
show_gdb_command_fn (vlib_main_t * vm,
                     unformat_input_t * input,
                     vlib_cli_command_t * cmd)
{
  vlib_cli_output (vm, "vl(p) returns vec_len(p)");
  vlib_cli_output (vm, "pe(p) returns pool_elts(p)");
  vlib_cli_output (vm, "pifi(p, i) returns pool_is_free_index(p, i)");
  vlib_cli_output (vm, "debug_hex_bytes (ptr, n_bytes) dumps n_bytes in hex");
  vlib_cli_output (vm, "vlib_dump_frame_ownership() does what it says");
  vlib_cli_output (vm, "vlib_runtime_index_to_node_name (index) prints NN");

  return 0;
}

VLIB_CLI_COMMAND (show_gdb_funcs_command, static) = {
  .path = "show gdb",
  .short_help = "Describe functions which can be called from gdb",
  .function = show_gdb_command_fn,
};

/* Cafeteria plan, maybe you don't want these functions */
clib_error_t * 
gdb_func_init (vlib_main_t * vm) { return 0; } 

VLIB_INIT_FUNCTION (gdb_func_init);
