/*
 * 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/tcp/tcp_debug.h>

tcp_dbg_main_t tcp_dbg_main;

void
tcp_evt_track_register (elog_track_t * et)
{
  tcp_dbg_main_t *tdm = &tcp_dbg_main;
  u32 fl_len, track_index;

  fl_len = vec_len (tdm->free_track_indices);
  if (fl_len)
    {
      track_index = tdm->free_track_indices[fl_len - 1];
      vec_dec_len (tdm->free_track_indices, 1);
      et->track_index_plus_one = track_index + 1;
    }
  else
    elog_track_register (&vlib_global_main.elog_main, et);
}

static const char *tcp_evt_grp_str[] = {
#define _(sym, str) str,
  foreach_tcp_evt_grp
#undef _
};

static void
tcp_debug_show_groups (void)
{
  tcp_dbg_main_t *tdm = &tcp_dbg_main;
  vlib_main_t *vm = vlib_get_main ();
  int i = 0;

  vlib_cli_output (vm, "%-10s%-30s%-10s", "Index", "Group", "Level");

  for (i = 0; i < TCP_EVT_N_GRP; i++)
    vlib_cli_output (vm, "%-10d%-30s%-10d", i, tcp_evt_grp_str[i],
		     tdm->grp_dbg_lvl[i]);
}

static void
tcp_debug_check_lc (void)
{
  tcp_dbg_main_t *tdm = &tcp_dbg_main;
  int i, have_enabled = 0;

  if (tdm->grp_dbg_lvl[TCP_EVT_GRP_LC])
    return;

  for (i = 0; i < TCP_EVT_N_GRP; i++)
    {
      if (tdm->grp_dbg_lvl[i])
	{
	  have_enabled = 1;
	  break;
	}
    }

  /* Make sure LC is enabled for track initialization */
  if (have_enabled)
    tdm->grp_dbg_lvl[TCP_EVT_GRP_LC] = 1;
}

static clib_error_t *
tcp_debug_fn (vlib_main_t * vm, unformat_input_t * input,
	      vlib_cli_command_t * cmd)
{
  unformat_input_t _line_input, *line_input = &_line_input;
  tcp_dbg_main_t *tdm = &tcp_dbg_main;
  u32 group = ~0, level = ~0;
  clib_error_t *error = 0;
  u8 is_show = 0;

  if (!TCP_DEBUG_ALWAYS)
    return clib_error_return (0, "must compile with TCP_DEBUG_ALWAYS set");

  if (!unformat_user (input, unformat_line_input, line_input))
    return clib_error_return (0, "expected enable | disable");

  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
    {
      if (unformat (line_input, "show"))
	is_show = 1;
      else if (unformat (line_input, "group %d", &group))
	;
      else if (unformat (line_input, "level %d", &level))
	;
      else
	{
	  error = clib_error_return (0, "unknown input `%U'",
				     format_unformat_error, line_input);
	  goto done;
	}
    }

  if (is_show)
    {
      tcp_debug_show_groups ();
      goto done;
    }
  if (group >= TCP_EVT_N_GRP)
    {
      error = clib_error_return (0, "group out of bounds");
      goto done;
    }
  if (group == ~0 || level == ~0)
    {
      error = clib_error_return (0, "group and level must be set");
      goto done;
    }

  tdm->grp_dbg_lvl[group] = level;

  tcp_debug_check_lc ();

done:

  unformat_free (line_input);
  return error;
}

/* *INDENT-OFF* */
VLIB_CLI_COMMAND (tcp_debug_command, static) =
{
  .path = "tcp debug",
  .short_help = "tcp [show] [debug group <N> level <N>]",
  .function = tcp_debug_fn,
};
/* *INDENT-ON* */

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