/*
 * 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 <vnet/vnet.h>
#include <vppinfra/error.h>

#include <vnet/lawful-intercept/lawful_intercept.h>

#include <vppinfra/error.h>
#include <vppinfra/elog.h>

extern vlib_node_registration_t li_hit_node;

typedef struct
{
  u32 next_index;
} li_hit_trace_t;

/* packet trace format function */
static u8 *
format_li_hit_trace (u8 * s, va_list * args)
{
  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
  li_hit_trace_t *t = va_arg (*args, li_hit_trace_t *);

  s = format (s, "LI_HIT: next index %d", t->next_index);

  return s;
}

#define foreach_li_hit_error                                    \
_(HITS, "LI packets processed")                                 \
_(NO_COLLECTOR, "No collector configured")                      \
_(BUFFER_ALLOCATION_FAILURE, "Buffer allocation failure")

typedef enum
{
#define _(sym,str) LI_HIT_ERROR_##sym,
  foreach_li_hit_error
#undef _
    LI_HIT_N_ERROR,
} li_hit_error_t;

static char *li_hit_error_strings[] = {
#define _(sym,string) string,
  foreach_li_hit_error
#undef _
};

typedef enum
{
  LI_HIT_NEXT_ETHERNET,
  LI_HIT_N_NEXT,
} li_hit_next_t;

VLIB_NODE_FN (li_hit_node) (vlib_main_t * vm,
			    vlib_node_runtime_t * node, vlib_frame_t * frame)
{
  u32 n_left_from, *from, *to_next;
  li_hit_next_t next_index;
  vlib_frame_t *int_frame = 0;
  u32 *to_int_next = 0;
  li_main_t *lm = &li_main;

  from = vlib_frame_vector_args (frame);
  n_left_from = frame->n_vectors;
  next_index = node->cached_next_index;

  if (PREDICT_FALSE (vec_len (lm->collectors) == 0))
    {
      vlib_node_increment_counter (vm, li_hit_node.index,
				   LI_HIT_ERROR_NO_COLLECTOR, n_left_from);
    }
  else
    {
      /* The intercept frame... */
      int_frame = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
      to_int_next = vlib_frame_vector_args (int_frame);
    }

  while (n_left_from > 0)
    {
      u32 n_left_to_next;

      vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);

#if 0
      while (n_left_from >= 4 && n_left_to_next >= 2)
	{
	  u32 next0 = LI_HIT_NEXT_INTERFACE_OUTPUT;
	  u32 next1 = LI_HIT_NEXT_INTERFACE_OUTPUT;
	  u32 sw_if_index0, sw_if_index1;
	  u8 tmp0[6], tmp1[6];
	  ethernet_header_t *en0, *en1;
	  u32 bi0, bi1;
	  vlib_buffer_t *b0, *b1;

	  /* Prefetch next iteration. */
	  {
	    vlib_buffer_t *p2, *p3;

	    p2 = vlib_get_buffer (vm, from[2]);
	    p3 = vlib_get_buffer (vm, from[3]);

	    vlib_prefetch_buffer_header (p2, LOAD);
	    vlib_prefetch_buffer_header (p3, LOAD);

	    CLIB_PREFETCH (p2->data, CLIB_CACHE_LINE_BYTES, STORE);
	    CLIB_PREFETCH (p3->data, CLIB_CACHE_LINE_BYTES, STORE);
	  }

	  /* speculatively enqueue b0 and b1 to the current next frame */
	  to_next[0] = bi0 = from[0];
	  to_next[1] = bi1 = from[1];
	  from += 2;
	  to_next += 2;
	  n_left_from -= 2;
	  n_left_to_next -= 2;

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

	  /* $$$$$ Dual loop: process 2 x packets here $$$$$ */
	  ASSERT (b0->current_data == 0);
	  ASSERT (b1->current_data == 0);

	  en0 = vlib_buffer_get_current (b0);
	  en1 = vlib_buffer_get_current (b1);

	  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
	  sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];

	  /* Send pkt back out the RX interface */
	  vnet_buffer (b0)->sw_if_index[VLIB_TX] = sw_if_index0;
	  vnet_buffer (b1)->sw_if_index[VLIB_TX] = sw_if_index1;

	  /* $$$$$ End of processing 2 x packets $$$$$ */

	  if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)))
	    {
	      if (b0->flags & VLIB_BUFFER_IS_TRACED)
		{
		  li_hit_trace_t *t =
		    vlib_add_trace (vm, node, b0, sizeof (*t));
		  t->sw_if_index = sw_if_index0;
		  t->next_index = next0;
		}
	      if (b1->flags & VLIB_BUFFER_IS_TRACED)
		{
		  li_hit_trace_t *t =
		    vlib_add_trace (vm, node, b1, sizeof (*t));
		  t->sw_if_index = sw_if_index1;
		  t->next_index = next1;
		}
	    }

	  /* verify speculative enqueues, maybe switch current next frame */
	  vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
					   to_next, n_left_to_next,
					   bi0, bi1, next0, next1);
	}
#endif /* $$$ dual-loop off */

      while (n_left_from > 0 && n_left_to_next > 0)
	{
	  u32 bi0;
	  vlib_buffer_t *b0;
	  vlib_buffer_t *c0;
	  ip4_udp_header_t *iu0;
	  ip4_header_t *ip0;
	  udp_header_t *udp0;
	  u32 next0 = LI_HIT_NEXT_ETHERNET;

	  /* speculatively enqueue b0 to the current next frame */
	  bi0 = from[0];
	  to_next[0] = bi0;
	  from += 1;
	  to_next += 1;
	  n_left_from -= 1;
	  n_left_to_next -= 1;

	  b0 = vlib_get_buffer (vm, bi0);
	  if (PREDICT_TRUE (to_int_next != 0))
	    {
	      /* Make an intercept copy. This can fail. */
	      c0 = vlib_buffer_copy (vm, b0);

	      if (PREDICT_FALSE (c0 == 0))
		{
		  vlib_node_increment_counter
		    (vm, node->node_index,
		     LI_HIT_ERROR_BUFFER_ALLOCATION_FAILURE, 1);
		  goto skip;
		}

	      vlib_buffer_advance (c0, -sizeof (*iu0));

	      iu0 = vlib_buffer_get_current (c0);
	      ip0 = &iu0->ip4;

	      ip0->ip_version_and_header_length = 0x45;
	      ip0->ttl = 254;
	      ip0->protocol = IP_PROTOCOL_UDP;

	      ip0->src_address.as_u32 = lm->src_addrs[0].as_u32;
	      ip0->dst_address.as_u32 = lm->collectors[0].as_u32;
	      ip0->length = vlib_buffer_length_in_chain (vm, c0);
	      ip0->checksum = ip4_header_checksum (ip0);

	      udp0 = &iu0->udp;
	      udp0->src_port = udp0->dst_port =
		clib_host_to_net_u16 (lm->ports[0]);
	      udp0->checksum = 0;
	      udp0->length =
		clib_net_to_host_u16 (vlib_buffer_length_in_chain (vm, b0));

	      to_int_next[0] = vlib_get_buffer_index (vm, c0);
	      to_int_next++;
	    }

	skip:
	  if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)
			     && (b0->flags & VLIB_BUFFER_IS_TRACED)))
	    {
	      li_hit_trace_t *t = vlib_add_trace (vm, node, b0, sizeof (*t));
	      t->next_index = next0;
	    }

	  /* verify speculative enqueue, maybe switch current next frame */
	  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
					   to_next, n_left_to_next,
					   bi0, next0);
	}

      vlib_put_next_frame (vm, node, next_index, n_left_to_next);
    }

  if (int_frame)
    {
      int_frame->n_vectors = frame->n_vectors;
      vlib_put_frame_to_node (vm, ip4_lookup_node.index, int_frame);
    }

  vlib_node_increment_counter (vm, li_hit_node.index,
			       LI_HIT_ERROR_HITS, frame->n_vectors);
  return frame->n_vectors;
}

/* *INDENT-OFF* */
VLIB_REGISTER_NODE (li_hit_node) = {
  .name = "li-hit",
  .vector_size = sizeof (u32),
  .format_trace = format_li_hit_trace,
  .type = VLIB_NODE_TYPE_INTERNAL,

  .n_errors = ARRAY_LEN(li_hit_error_strings),
  .error_strings = li_hit_error_strings,

  .n_next_nodes = LI_HIT_N_NEXT,

  /* edit / add dispositions here */
  .next_nodes = {
        [LI_HIT_NEXT_ETHERNET] = "ethernet-input-not-l2",
  },
};
/* *INDENT-ON* */

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