/*
 * drop.c - Punt and drop nodes
 *
 * 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.
 */

#include <vlib/vlib.h>
#include <vppinfra/vector/count_equal.h>

typedef enum
{
  ERROR_DISPOSITION_DROP,
  ERROR_DISPOSITION_PUNT,
  ERROR_N_DISPOSITION,
} error_disposition_t;

static u8 *
validate_error (vlib_main_t * vm, vlib_error_t * e, u32 index)
{
  uword node_index = vlib_error_get_node (&vm->node_main, e[0]);
  uword code = vlib_error_get_code (&vm->node_main, e[0]);
  vlib_node_t *n;

  if (node_index >= vec_len (vm->node_main.nodes))
    return format (0, "[%d], node index out of range 0x%x, error 0x%x",
		   index, node_index, e[0]);

  n = vlib_get_node (vm, node_index);
  if (code >= n->n_errors)
    return format (0, "[%d], code %d out of range for node %v",
		   index, code, n->name);

  return 0;
}

static u8 *
validate_error_frame (vlib_main_t * vm,
		      vlib_node_runtime_t * node, vlib_frame_t * f)
{
  u32 *buffers = vlib_frame_vector_args (f);
  vlib_buffer_t *b;
  u8 *msg = 0;
  uword i;

  for (i = 0; i < f->n_vectors; i++)
    {
      b = vlib_get_buffer (vm, buffers[i]);
      msg = validate_error (vm, &b->error, i);
      if (msg)
	return msg;
    }

  return msg;
}

always_inline u32
counter_index (vlib_main_t * vm, vlib_error_t e)
{
  vlib_node_t *n;
  u32 ci, ni;

  ni = vlib_error_get_node (&vm->node_main, e);
  n = vlib_get_node (vm, ni);

  ci = vlib_error_get_code (&vm->node_main, e);
  if (ci >= n->n_errors)
    return CLIB_U32_MAX;

  ci += n->error_heap_index;

  return ci;
}

static u8 *
format_error_trace (u8 * s, va_list * va)
{
  vlib_main_t *vm = va_arg (*va, vlib_main_t *);
  CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *);
  vlib_error_t *e = va_arg (*va, vlib_error_t *);
  vlib_node_t *error_node;
  vlib_error_main_t *em = &vm->error_main;
  u32 i;

  error_node = vlib_get_node (vm, vlib_error_get_node (&vm->node_main, e[0]));
  i = counter_index (vm, vlib_error_get_code (&vm->node_main, e[0]));
  if (i != CLIB_U32_MAX)
    {
      i += error_node->error_heap_index;
      s = format (s, "%v: %s", error_node->name, em->counters_heap[i].desc);
    }

  return s;
}

static void
trace_errors (vlib_main_t * vm,
	      vlib_node_runtime_t * node, vlib_frame_t * frame)
{
  u32 n_left, *buffers;

  buffers = vlib_frame_vector_args (frame);
  n_left = frame->n_vectors;

  while (n_left >= 4)
    {
      u32 bi0, bi1;
      vlib_buffer_t *b0, *b1;
      vlib_error_t *t0, *t1;

      /* Prefetch next iteration. */
      vlib_prefetch_buffer_with_index (vm, buffers[2], LOAD);
      vlib_prefetch_buffer_with_index (vm, buffers[3], LOAD);

      bi0 = buffers[0];
      bi1 = buffers[1];

      b0 = vlib_get_buffer (vm, bi0);
      b1 = vlib_get_buffer (vm, bi1);

      if (b0->flags & VLIB_BUFFER_IS_TRACED)
	{
	  t0 = vlib_add_trace (vm, node, b0, sizeof (t0[0]));
	  t0[0] = b0->error;
	}
      if (b1->flags & VLIB_BUFFER_IS_TRACED)
	{
	  t1 = vlib_add_trace (vm, node, b1, sizeof (t1[0]));
	  t1[0] = b1->error;
	}
      buffers += 2;
      n_left -= 2;
    }

  while (n_left >= 1)
    {
      u32 bi0;
      vlib_buffer_t *b0;
      vlib_error_t *t0;

      bi0 = buffers[0];

      b0 = vlib_get_buffer (vm, bi0);

      if (b0->flags & VLIB_BUFFER_IS_TRACED)
	{
	  t0 = vlib_add_trace (vm, node, b0, sizeof (t0[0]));
	  t0[0] = b0->error;
	}
      buffers += 1;
      n_left -= 1;
    }
}

static_always_inline uword
process_drop_punt (vlib_main_t * vm,
		   vlib_node_runtime_t * node,
		   vlib_frame_t * frame, error_disposition_t disposition)
{
  u32 errors[VLIB_FRAME_SIZE], *error, *from, n_left;
  vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b;
  vlib_error_main_t *em = &vm->error_main;

  from = vlib_frame_vector_args (frame);
  n_left = frame->n_vectors;
  b = bufs;
  error = errors;

  vlib_get_buffers (vm, from, bufs, n_left);

  if (node->flags & VLIB_NODE_FLAG_TRACE)
    trace_errors (vm, node, frame);

  /* collect the array of error first ... */
  while (n_left >= 4)
    {
      if (n_left >= 12)
	{
	  /* Prefetch 8 ahead - there's not much going on in each iteration */
	  vlib_prefetch_buffer_header (b[4], LOAD);
	  vlib_prefetch_buffer_header (b[5], LOAD);
	  vlib_prefetch_buffer_header (b[6], LOAD);
	  vlib_prefetch_buffer_header (b[7], LOAD);
	}
      error[0] = b[0]->error;
      error[1] = b[1]->error;
      error[2] = b[2]->error;
      error[3] = b[3]->error;

      error += 4;
      n_left -= 4;
      b += 4;
    }
  while (n_left)
    {
      error[0] = b[0]->error;

      error += 1;
      n_left -= 1;
      b += 1;
    }

  /* ... then count against them in blocks */
  n_left = frame->n_vectors;

  while (n_left)
    {
      u16 off, count;
      u32 c_index;

      off = frame->n_vectors - n_left;

      error = errors + off;

      count = clib_count_equal_u32 (error, n_left);
      n_left -= count;

      c_index = counter_index (vm, error[0]);
      if (c_index != CLIB_U32_MAX)
	em->counters[c_index] += count;

      vlib_error_elog_count (vm, c_index, count);
    }

  if (disposition == ERROR_DISPOSITION_DROP || !vm->os_punt_frame)
    {
      vlib_buffer_free (vm, from, frame->n_vectors);

      /* If there is no punt function, free the frame as well. */
      if (disposition == ERROR_DISPOSITION_PUNT && !vm->os_punt_frame)
	vlib_frame_free (vm, frame);
    }
  else
    vm->os_punt_frame (vm, node, frame);

  return frame->n_vectors;
}

VLIB_NODE_FN (error_drop_node) (vlib_main_t * vm,
				vlib_node_runtime_t * node,
				vlib_frame_t * frame)
{
  return process_drop_punt (vm, node, frame, ERROR_DISPOSITION_DROP);
}

VLIB_NODE_FN (error_punt_node) (vlib_main_t * vm,
				vlib_node_runtime_t * node,
				vlib_frame_t * frame)
{
  return process_drop_punt (vm, node, frame, ERROR_DISPOSITION_PUNT);
}

VLIB_REGISTER_NODE (error_drop_node) = {
  .name = "drop",
  .flags = VLIB_NODE_FLAG_IS_DROP,
  .vector_size = sizeof (u32),
  .format_trace = format_error_trace,
  .validate_frame = validate_error_frame,
};

VLIB_REGISTER_NODE (error_punt_node) = {
  .name = "punt",
  .flags = (VLIB_NODE_FLAG_FRAME_NO_FREE_AFTER_DISPATCH
	    | VLIB_NODE_FLAG_IS_PUNT),
  .vector_size = sizeof (u32),
  .format_trace = format_error_trace,
  .validate_frame = validate_error_frame,
};

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