/*
 * Copyright (c) 2017-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/session/application_namespace.h>
#include <vnet/session/application.h>
#include <vnet/session/session_table.h>
#include <vnet/session/session.h>
#include <vnet/fib/fib_table.h>
#include <vppinfra/file.h>
#include <vppinfra/format_table.h>
#include <vlib/unix/unix.h>

/**
 * Hash table of application namespaces by app ns ids
 */
uword *app_namespace_lookup_table;

/**
 * Pool of application namespaces
 */
static app_namespace_t *app_namespace_pool;

static u8 app_sapi_enabled;

app_namespace_t *
app_namespace_get (u32 index)
{
  return pool_elt_at_index (app_namespace_pool, index);
}

app_namespace_t *
app_namespace_get_from_id (const u8 *ns_id)
{
  u32 index = app_namespace_index_from_id (ns_id);
  if (index == APP_NAMESPACE_INVALID_INDEX)
    return 0;
  return app_namespace_get (index);
}

u32
app_namespace_index (app_namespace_t * app_ns)
{
  return (app_ns - app_namespace_pool);
}

void
app_namespace_free (app_namespace_t *app_ns)
{
  hash_unset_mem (app_namespace_lookup_table, app_ns->ns_id);
  vec_free (app_ns->ns_id);

  pool_put (app_namespace_pool, app_ns);
}

app_namespace_t *
app_namespace_alloc (const u8 *ns_id)
{
  app_namespace_t *app_ns;

  pool_get (app_namespace_pool, app_ns);
  clib_memset (app_ns, 0, sizeof (*app_ns));

  app_ns->ns_id = vec_dup ((u8 *) ns_id);
  vec_terminate_c_string (app_ns->ns_id);

  hash_set_mem (app_namespace_lookup_table, app_ns->ns_id,
		app_ns - app_namespace_pool);

  return app_ns;
}

int
vnet_app_namespace_add_del (vnet_app_namespace_add_del_args_t * a)
{
  app_namespace_t *app_ns;
  session_table_t *st;
  u32 ns_index;
  int rv;

  if (a->is_add)
    {
      if (a->sw_if_index != APP_NAMESPACE_INVALID_INDEX
	  && !vnet_get_sw_interface_or_null (vnet_get_main (),
					     a->sw_if_index))
	return VNET_API_ERROR_INVALID_SW_IF_INDEX;


      if (a->sw_if_index != APP_NAMESPACE_INVALID_INDEX)
	{
	  a->ip4_fib_id =
	    fib_table_get_table_id_for_sw_if_index (FIB_PROTOCOL_IP4,
						    a->sw_if_index);
	  a->ip6_fib_id =
	    fib_table_get_table_id_for_sw_if_index (FIB_PROTOCOL_IP6,
						    a->sw_if_index);
	}
      if (a->sw_if_index == APP_NAMESPACE_INVALID_INDEX
	  && a->ip4_fib_id == APP_NAMESPACE_INVALID_INDEX)
	return VNET_API_ERROR_INVALID_VALUE;

      app_ns = app_namespace_get_from_id (a->ns_id);
      if (!app_ns)
	{
	  app_ns = app_namespace_alloc (a->ns_id);
	  st = session_table_alloc ();
	  session_table_init (st, FIB_PROTOCOL_MAX);
	  st->is_local = 1;
	  st->appns_index = app_namespace_index (app_ns);
	  app_ns->local_table_index = session_table_index (st);
	  if (a->netns)
	    {
	      app_ns->netns = vec_dup (a->netns);
	      vec_terminate_c_string (app_ns->netns);
	    }
	  if (a->sock_name)
	    {
	      app_ns->sock_name = vec_dup (a->sock_name);
	      vec_terminate_c_string (app_ns->sock_name);
	    }

	  /* Add socket for namespace,
	   * only at creation time */
	  if (app_sapi_enabled)
	    {
	      rv = appns_sapi_add_ns_socket (app_ns);
	      if (rv)
		return rv;
	    }
	}

      app_ns->ns_secret = a->secret;
      app_ns->sw_if_index = a->sw_if_index;
      app_ns->ip4_fib_index =
	fib_table_find (FIB_PROTOCOL_IP4, a->ip4_fib_id);
      app_ns->ip6_fib_index =
	fib_table_find (FIB_PROTOCOL_IP6, a->ip6_fib_id);
      session_lookup_set_tables_appns (app_ns);

    }
  else
    {
      ns_index = app_namespace_index_from_id (a->ns_id);
      if (ns_index == APP_NAMESPACE_INVALID_INDEX)
	return VNET_API_ERROR_INVALID_VALUE;

      app_ns = app_namespace_get (ns_index);
      if (!app_ns)
	return VNET_API_ERROR_INVALID_VALUE;

      application_namespace_cleanup (app_ns);

      if (app_sapi_enabled)
	appns_sapi_del_ns_socket (app_ns);

      st = session_table_get (app_ns->local_table_index);

      session_table_free (st, FIB_PROTOCOL_MAX);
      if (app_ns->netns)
	vec_free (app_ns->netns);
      if (app_ns->sock_name)
	vec_free (app_ns->sock_name);

      app_namespace_free (app_ns);
    }

  return 0;
}

const u8 *
app_namespace_id (app_namespace_t * app_ns)
{
  return app_ns->ns_id;
}

u32
app_namespace_index_from_id (const u8 * ns_id)
{
  uword *indexp;
  u8 *key;

  key = vec_dup ((u8 *) ns_id);
  vec_terminate_c_string (key);

  indexp = hash_get_mem (app_namespace_lookup_table, key);
  vec_free (key);
  if (!indexp)
    return APP_NAMESPACE_INVALID_INDEX;
  return *indexp;
}

const u8 *
app_namespace_id_from_index (u32 index)
{
  app_namespace_t *app_ns;

  app_ns = app_namespace_get (index);
  return app_namespace_id (app_ns);
}

u32
app_namespace_get_fib_index (app_namespace_t * app_ns, u8 fib_proto)
{
  return fib_proto == FIB_PROTOCOL_IP4 ?
    app_ns->ip4_fib_index : app_ns->ip6_fib_index;
}

session_table_t *
app_namespace_get_local_table (app_namespace_t * app_ns)
{
  return session_table_get (app_ns->local_table_index);
}

int
appns_sapi_enable_disable (int is_enable)
{
  /* This cannot be called with active sockets */
  if (pool_elts (app_namespace_pool))
    return -1;

  app_sapi_enabled = is_enable;
  return 0;
}

u8
appns_sapi_enabled (void)
{
  return app_sapi_enabled;
}

void
app_namespaces_init (void)
{
  u8 *ns_id = format (0, "default");

  if (!app_namespace_lookup_table)
    app_namespace_lookup_table =
      hash_create_vec (0, sizeof (u8), sizeof (uword));

  /*
   * Allocate default namespace
   */

  /* clang-format off */
  vnet_app_namespace_add_del_args_t a = {
    .ns_id = ns_id,
    .netns = 0,
    .sock_name = 0,
    .secret = 0,
    .sw_if_index = APP_NAMESPACE_INVALID_INDEX,
    .is_add = 1
  };
  /* clang-format on */

  vnet_app_namespace_add_del (&a);
  vec_free (ns_id);
}

static clib_error_t *
app_ns_fn (vlib_main_t * vm, unformat_input_t * input,
	   vlib_cli_command_t * cmd)
{
  u8 is_add = 0, *ns_id = 0, secret_set = 0, sw_if_index_set = 0;
  u8 *netns = 0, *sock_name = 0;
  unformat_input_t _line_input, *line_input = &_line_input;
  u32 sw_if_index, fib_id = APP_NAMESPACE_INVALID_INDEX;
  vnet_main_t *vnm = vnet_get_main ();
  u64 secret;
  clib_error_t *error = 0;
  int rv;

  session_cli_return_if_not_enabled ();

  if (!unformat_user (input, unformat_line_input, line_input))
    return 0;

  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
    {
      if (unformat (line_input, "add"))
	is_add = 1;
      else if (unformat (line_input, "del"))
	is_add = 0;
      else if (unformat (line_input, "id %_%v%_", &ns_id))
	;
      else if (unformat (line_input, "secret %lu", &secret))
	secret_set = 1;
      else if (unformat (line_input, "sw_if_index %u", &sw_if_index))
	sw_if_index_set = 1;
      else if (unformat (line_input, "if %U", unformat_vnet_sw_interface, vnm,
			 &sw_if_index))
	sw_if_index_set = 1;
      else if (unformat (line_input, "fib_id", &fib_id))
	;
      else if (unformat (line_input, "netns %_%v%_", &netns))
	;
      else if (unformat (line_input, "sock-name %_%v%_", &sock_name))
	;
      else
	{
	  error = clib_error_return (0, "unknown input `%U'",
				     format_unformat_error, line_input);
	  goto done;
	}
    }

  if (!ns_id)
    {
      vlib_cli_output (vm, "namespace-id must be provided");
      goto done;
    }

  if (is_add && (!secret_set || !sw_if_index_set))
    {
      vlib_cli_output (vm, "secret and interface must be provided");
      goto done;
    }

  /* clang-format off */
  vnet_app_namespace_add_del_args_t args = {
    .ns_id = ns_id,
    .netns = netns,
    .secret = secret,
    .sw_if_index = sw_if_index,
    .sock_name = sock_name,
    .ip4_fib_id = fib_id,
    .is_add = is_add,
  };
  /* clang-format on */

  if ((rv = vnet_app_namespace_add_del (&args)))
    error = clib_error_return (0, "app namespace add del returned %d", rv);

done:

  vec_free (ns_id);
  vec_free (netns);
  vec_free (sock_name);
  unformat_free (line_input);

  return error;
}

/* *INDENT-OFF* */
VLIB_CLI_COMMAND (app_ns_command, static) = {
  .path = "app ns",
  .short_help = "app ns [add|del] id <namespace-id> secret <secret> "
		"sw_if_index <sw_if_index> if <interface> [netns <ns>]",
  .function = app_ns_fn,
};
/* *INDENT-ON* */

u8 *
format_app_namespace (u8 * s, va_list * args)
{
  app_namespace_t *app_ns = va_arg (*args, app_namespace_t *);
  vnet_main_t *vnm = vnet_get_main ();

  s = format (s, "Application namespace [%u]\nid:        %s\nsecret:    %lu",
	      app_namespace_index (app_ns), app_ns->ns_id, app_ns->ns_secret);
  if (app_ns->sw_if_index != (u32) ~0)
    s = format (s, "\nInterface: %U", format_vnet_sw_if_index_name, vnm,
		app_ns->sw_if_index);
  if (app_ns->netns)
    s = format (s, "\nNetns:     %s", app_ns->netns);
  if (app_ns->sock_name)
    s = format (s, "\nSocket:    %s", app_ns->sock_name);

  return s;
}

static void
app_namespace_show_api (vlib_main_t * vm, app_namespace_t * app_ns)
{
  app_ns_api_handle_t *handle;
  app_worker_t *app_wrk;
  clib_socket_t *cs;
  clib_file_t *cf;

  if (!app_sapi_enabled)
    {
      vlib_cli_output (vm, "app socket api not enabled!");
      return;
    }

  vlib_cli_output (vm, "socket: %v\n", app_ns->sock_name);

  if (!pool_elts (app_ns->app_sockets))
    return;

  vlib_cli_output (vm, "%12s%12s%5s", "app index", "wrk index", "fd");


  /* *INDENT-OFF* */
  pool_foreach (cs, app_ns->app_sockets)  {
    handle = (app_ns_api_handle_t *) &cs->private_data;
    cf = clib_file_get (&file_main, handle->aah_file_index);
    if (handle->aah_app_wrk_index == APP_INVALID_INDEX)
      {
	vlib_cli_output (vm, "%12d%12d%5u", -1, -1, cf->file_descriptor);
	continue;
      }
    app_wrk = app_worker_get (handle->aah_app_wrk_index);
    vlib_cli_output (vm, "%12d%12d%5u", app_wrk->app_index,
                     app_wrk->wrk_map_index, cf->file_descriptor);
  }
  /* *INDENT-ON* */
}

static clib_error_t *
show_app_ns_fn (vlib_main_t * vm, unformat_input_t * main_input,
		vlib_cli_command_t * cmd)
{
  unformat_input_t _line_input, *line_input = &_line_input;
  u8 *ns_id = 0, do_table = 0, had_input = 1, do_api = 0;
  app_namespace_t *app_ns;
  vnet_main_t *vnm = vnet_get_main ();
  session_table_t *st;
  table_t table = {}, *t = &table;

  session_cli_return_if_not_enabled ();

  if (!unformat_user (main_input, unformat_line_input, line_input))
    {
      had_input = 0;
      goto do_ns_list;
    }

  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
    {
      if (unformat (line_input, "id %_%v%_", &ns_id))
	do_table = 1;
      else if (unformat (line_input, "api-clients"))
	do_api = 1;
      else
	{
	  vlib_cli_output (vm, "unknown input [%U]", format_unformat_error,
			   line_input);
	  goto done;
	}
    }

  if (do_api)
    {
      if (!do_table)
	{
	  vlib_cli_output (vm, "must specify a table for api");
	  goto done;
	}
      app_ns = app_namespace_get_from_id (ns_id);
      app_namespace_show_api (vm, app_ns);
      goto done;
    }
  if (do_table)
    {
      app_ns = app_namespace_get_from_id (ns_id);
      if (!app_ns)
	{
	  vlib_cli_output (vm, "ns %v not found", ns_id);
	  goto done;
	}
      st = session_table_get (app_ns->local_table_index);
      if (!st)
	{
	  vlib_cli_output (vm, "table for ns %v could not be found", ns_id);
	  goto done;
	}
      vlib_cli_output (vm, "%U", format_app_namespace, app_ns);
      session_lookup_show_table_entries (vm, st, 0, 1);
      vec_free (ns_id);
      goto done;
    }

do_ns_list:
  table_add_header_col (t, 6, "Index", "Secret", "Interface", "Id", "Netns",
			"Socket");
  int i = 0;
  pool_foreach (app_ns, app_namespace_pool)
    {
      int j = 0;
      table_format_cell (t, i, j++, "%u", app_namespace_index (app_ns));
      table_format_cell (t, i, j++, "%lu", app_ns->ns_secret);
      table_format_cell (t, i, j++, "%U", format_vnet_sw_if_index_name, vnm,
			 app_ns->sw_if_index);
      table_format_cell (t, i, j++, "%s", app_ns->ns_id);
      table_format_cell (t, i, j++, "%s", app_ns->netns);
      table_format_cell (t, i++, j++, "%s", app_ns->sock_name);
    }

  t->default_body.align = TTAA_LEFT;
  t->default_header_col.align = TTAA_LEFT;
  t->default_header_col.fg_color = TTAC_YELLOW;
  t->default_header_col.flags = TTAF_FG_COLOR_SET;
  vlib_cli_output (vm, "%U", format_table, t);
  table_free (t);

done:
  if (had_input)
    unformat_free (line_input);
  return 0;
}

/* *INDENT-OFF* */
VLIB_CLI_COMMAND (show_app_ns_command, static) = {
  .path = "show app ns",
  .short_help = "show app ns [id <id> [api-clients]]",
  .function = show_app_ns_fn,
};
/* *INDENT-ON* */

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