/* Hey Emacs use -*- mode: C -*- */
/*
 * Copyright 2020 Rubicon Communications, LLC.
 *
 * 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/vnet.h>
#include <vlibmemory/api.h>

#include <tracedump/graph.api_enum.h>
#include <tracedump/graph.api_types.h>

#define REPLY_MSG_ID_BASE	gmp->msg_id_base
#include <vlibapi/api_helper_macros.h>

#include <tracedump/graph.h>


graph_main_t graph_main;


#define MIN(x,y)	(((x) < (y)) ? (x) : (y))


/*
 * If ever the graph or set of nodes changes, this cache of
 * nodes in sorted order should be invalidated.
 */
void
graph_node_invalid_cache (void)
{
  graph_main_t *gmp = &graph_main;

  vec_free (gmp->sorted_node_vec);
}


static clib_error_t *
graph_node_cache_reaper (u32 client_index)
{
  graph_node_invalid_cache ();
  return 0;
}

VL_MSG_API_REAPER_FUNCTION (graph_node_cache_reaper);


static void
send_graph_node_reply (vl_api_registration_t * rp,
		       u32 context, u32 retval, u32 cursor)
{
  graph_main_t *gmp = &graph_main;
  vl_api_graph_node_get_reply_t *rmp;

  rmp = vl_msg_api_alloc (sizeof (*rmp));
  rmp->_vl_msg_id = htons (VL_API_GRAPH_NODE_GET_REPLY + gmp->msg_id_base);
  rmp->context = context;
  rmp->retval = clib_host_to_net_u32 (retval);
  rmp->cursor = htonl (cursor);

  vl_api_send_msg (rp, (u8 *) rmp);
}


static void
send_graph_node_details (vlib_node_main_t * nm,
			 vl_api_registration_t * reg,
			 u32 context, vlib_node_t * n, bool want_arcs)
{
  graph_main_t *gmp = &graph_main;
  vl_api_graph_node_details_t *mp;
  u32 msg_size;

  msg_size = sizeof (*mp);
  if (want_arcs)
    msg_size += vec_len (n->next_nodes) * sizeof (*n->next_nodes);

  mp = vl_msg_api_alloc (msg_size);
  if (!mp)
    return;

  clib_memset (mp, 0, msg_size);

  mp->_vl_msg_id = htons (VL_API_GRAPH_NODE_DETAILS + gmp->msg_id_base);
  mp->context = context;
  mp->index = htonl (n->index);
  mp->flags = htonl (n->flags);

  clib_strncpy ((char *) mp->name, (char *) n->name,
		MIN (sizeof (mp->name) - 1, vec_len (n->name)));

  if (want_arcs)
    {
      int i;

      mp->n_arcs = htonl (vec_len (n->next_nodes));
      for (i = 0; i < vec_len (n->next_nodes); ++i)
	{
	  mp->arcs_out[i] = htonl (n->next_nodes[i]);
	}
    }

  vl_api_send_msg (reg, (u8 *) mp);
}


static int
node_cmp (void *a1, void *a2)
{
  vlib_node_t **n1 = a1;
  vlib_node_t **n2 = a2;

  return vec_cmp (n1[0]->name, n2[0]->name);
}


/*
 * When cursor == ~0, it begins a request:
 *    if index != ~0, dump node with given index
 *    if index == ~0 and name[0] != 0, dump node with given name
 *    if index == ~0 and name[0] == 0, and flag != 0, dump flagged nodes
 *    else
 *        index == ~0 and name[0] == 0 and flag == 0, so dump all nodes.
 *
 * When cursor != ~0, it is the middle of a request:
 *    The same (index, name, and flag) parameters are assumed,
 *    The next results resume from cursor.
 */
static void
vl_api_graph_node_get_t_handler (vl_api_graph_node_get_t * mp)
{
  vl_api_registration_t *rp;

  rp = vl_api_client_index_to_registration (mp->client_index);
  if (!rp)
    return;

  vlib_main_t *vm = vlib_get_main ();
  vlib_node_main_t *nm = &vm->node_main;
  graph_main_t *gmp = &graph_main;
  vlib_node_t *n;
  u32 cursor;
  u32 node_index;
  bool want_arcs;

  want_arcs = ! !mp->want_arcs;
  cursor = ntohl (mp->cursor);
  n = 0;

  /*
   * Return details on a specific node by index?
   */
  node_index = ntohl (mp->index);
  if (cursor == ~0 && node_index != ~0)
    {
      if (node_index < vec_len (nm->nodes))
	n = vlib_get_node (vm, node_index);
      if (!n)
	{
	  send_graph_node_reply (rp, mp->context,
				 VNET_API_ERROR_NO_SUCH_ENTRY, ~0);
	  return;
	}
      send_graph_node_details (nm, rp, mp->context, n, want_arcs);
      send_graph_node_reply (rp, mp->context, 0, ~0);
      return;
    }

  /*
   * Return details on a specific node by name?
   */
  if (cursor == ~0 && mp->name[0] != 0)
    {
      n = vlib_get_node_by_name (vm, (u8 *) mp->name);
      if (!n)
	{
	  send_graph_node_reply (rp, mp->context,
				 VNET_API_ERROR_NO_SUCH_ENTRY, ~0);
	  return;
	}

      send_graph_node_details (nm, rp, mp->context, n, want_arcs);
      send_graph_node_reply (rp, mp->context, 0, ~0);
      return;
    }

  /*
   * Inspect all nodes, but potentially limit them by flag selection.
   * As iteration my need to occur over multiple streaming API calls,
   * determine the API client index and cache a sorted list of nodes.
   *
   * First time through, make a sorted node list and cache it.
   */
  vlib_node_t **nodes = gmp->sorted_node_vec;
  if (!nodes)
    {
      nodes = vec_dup (nm->nodes);
      vec_sort_with_function (nodes, node_cmp);
      gmp->sorted_node_vec = nodes;
    }

  u32 flags = ntohl (mp->flags);
  u32 first_index = (cursor == ~0) ? 0 : cursor;

  /* Don't overflow the existing queue space. */
  svm_queue_t *q = rp->vl_input_queue;
  u32 queue_slots_available = q->maxsize - q->cursize;
  int chunk = (queue_slots_available > 0) ? queue_slots_available - 1 : 0;
  u32 i;

  for (i = first_index; i < vec_len (nodes); ++i)
    {
      if (chunk-- == 0)
	{
	  /*
	   * Pick up again at cursor = i.
	   */
	  send_graph_node_reply (rp, mp->context, VNET_API_ERROR_EAGAIN, i);
	  return;
	}

      n = nodes[i];
      if (flags == 0 || (n->flags & flags))
	{
	  send_graph_node_details (nm, rp, mp->context, n, want_arcs);
	}
    }

  send_graph_node_reply (rp, mp->context, 0, ~0);
}


#include <vnet/format_fns.h>
#include <tracedump/graph.api.c>

static clib_error_t *
graph_api_hookup (vlib_main_t * vm)
{
  api_main_t *am = vlibapi_get_main ();
  graph_main_t *gmp = &graph_main;

  gmp->msg_id_base = setup_message_id_table ();

  vl_api_set_msg_thread_safe (am, gmp->msg_id_base + VL_API_GRAPH_NODE_GET, 1);

  return 0;
}

VLIB_INIT_FUNCTION (graph_api_hookup);

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