/* SPDX-License-Identifier: Apache-2.0
 * Copyright(c) 2022 Cisco Systems, Inc.
 */

#include <vnet/udp/udp.h>
#include <vnet/ip/ip4_inlines.h>
#include <vnet/ip/ip6_inlines.h>

#define udp_node_index(node_id, is_ip4)                                       \
  ((is_ip4) ? udp4_##node_id##_node.index : udp6_##node_id##_node.index)

typedef enum udp_output_next_
{
  UDP_OUTPUT_NEXT_DROP,
  UDP_OUTPUT_NEXT_IP_LOOKUP,
  UDP_OUTPUT_N_NEXT
} udp_output_next_t;

#define foreach_udp4_output_next                                              \
  _ (DROP, "error-drop")                                                      \
  _ (IP_LOOKUP, "ip4-lookup")

#define foreach_udp6_output_next                                              \
  _ (DROP, "error-drop")                                                      \
  _ (IP_LOOKUP, "ip6-lookup")

static vlib_error_desc_t udp_output_error_counters[] = {
#define udp_error(f, n, s, d) { #n, d, VL_COUNTER_SEVERITY_##s },
#include <vnet/udp/udp_error.def>
#undef udp_error
};

typedef struct udp_tx_trace_
{
  udp_header_t udp_header;
  udp_connection_t udp_connection;
} udp_tx_trace_t;

static u8 *
format_udp_tx_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 *);
  udp_tx_trace_t *t = va_arg (*args, udp_tx_trace_t *);
  udp_connection_t *uc = &t->udp_connection;
  u32 indent = format_get_indent (s);

  s = format (s, "%U\n%U%U", format_udp_connection, uc, format_white_space,
	      indent, format_udp_header, &t->udp_header, 128);

  return s;
}

static void
udp46_output_trace_frame (vlib_main_t *vm, vlib_node_runtime_t *node,
			  u32 *to_next, u32 n_bufs)
{
  udp_connection_t *uc;
  udp_tx_trace_t *t;
  vlib_buffer_t *b;
  udp_header_t *uh;
  int i;

  for (i = 0; i < n_bufs; i++)
    {
      b = vlib_get_buffer (vm, to_next[i]);
      if (!(b->flags & VLIB_BUFFER_IS_TRACED))
	continue;
      uh = vlib_buffer_get_current (b);
      uc = udp_connection_get (vnet_buffer (b)->tcp.connection_index,
			       vm->thread_index);
      t = vlib_add_trace (vm, node, b, sizeof (*t));
      clib_memcpy_fast (&t->udp_header, uh, sizeof (t->udp_header));
      clib_memcpy_fast (&t->udp_connection, uc, sizeof (t->udp_connection));
    }
}

always_inline void
udp_output_handle_packet (udp_connection_t *uc0, vlib_buffer_t *b0,
			  vlib_node_runtime_t *error_node, u16 *next0,
			  u8 is_ip4)
{
  /* If next_index is not drop use it */
  if (uc0->next_node_index)
    {
      *next0 = uc0->next_node_index;
      vnet_buffer (b0)->tcp.next_node_opaque = uc0->next_node_opaque;
    }
  else
    {
      *next0 = UDP_OUTPUT_NEXT_IP_LOOKUP;
    }

  vnet_buffer (b0)->sw_if_index[VLIB_TX] = uc0->c_fib_index;
  vnet_buffer (b0)->sw_if_index[VLIB_RX] = uc0->sw_if_index;
}

always_inline udp_connection_t *
udp_output_get_connection (vlib_buffer_t *b, u32 thread_index)
{
  if (PREDICT_FALSE (vnet_buffer (b)->tcp.flags & UDP_CONN_F_LISTEN))
    return udp_listener_get (vnet_buffer (b)->tcp.connection_index);

  return udp_connection_get (vnet_buffer (b)->tcp.connection_index,
			     thread_index);
}

always_inline uword
udp46_output_inline (vlib_main_t *vm, vlib_node_runtime_t *node,
		     vlib_frame_t *frame, int is_ip4)
{
  u32 n_left_from, *from, thread_index = vm->thread_index;
  vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b;
  u16 nexts[VLIB_FRAME_SIZE], *next;

  from = vlib_frame_vector_args (frame);
  n_left_from = frame->n_vectors;

  if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE))
    udp46_output_trace_frame (vm, node, from, n_left_from);

  vlib_get_buffers (vm, from, bufs, n_left_from);
  b = bufs;
  next = nexts;

  while (n_left_from >= 4)
    {
      udp_connection_t *uc0, *uc1;

      vlib_prefetch_buffer_header (b[2], STORE);
      CLIB_PREFETCH (b[2]->data, 2 * CLIB_CACHE_LINE_BYTES, STORE);

      vlib_prefetch_buffer_header (b[3], STORE);
      CLIB_PREFETCH (b[3]->data, 2 * CLIB_CACHE_LINE_BYTES, STORE);

      uc0 = udp_output_get_connection (b[0], thread_index);
      uc1 = udp_output_get_connection (b[1], thread_index);

      if (PREDICT_TRUE (!uc0 + !uc1 == 0))
	{
	  udp_output_handle_packet (uc0, b[0], node, &next[0], is_ip4);
	  udp_output_handle_packet (uc1, b[1], node, &next[1], is_ip4);
	}
      else
	{
	  if (uc0 != 0)
	    {
	      udp_output_handle_packet (uc0, b[0], node, &next[0], is_ip4);
	    }
	  else
	    {
	      b[0]->error = node->errors[UDP_ERROR_INVALID_CONNECTION];
	      next[0] = UDP_OUTPUT_NEXT_DROP;
	    }
	  if (uc1 != 0)
	    {
	      udp_output_handle_packet (uc1, b[1], node, &next[1], is_ip4);
	    }
	  else
	    {
	      b[1]->error = node->errors[UDP_ERROR_INVALID_CONNECTION];
	      next[1] = UDP_OUTPUT_NEXT_DROP;
	    }
	}

      b += 2;
      next += 2;
      n_left_from -= 2;
    }
  while (n_left_from > 0)
    {
      udp_connection_t *uc0;

      if (n_left_from > 1)
	{
	  vlib_prefetch_buffer_header (b[1], STORE);
	  CLIB_PREFETCH (b[1]->data, 2 * CLIB_CACHE_LINE_BYTES, STORE);
	}

      uc0 = udp_output_get_connection (b[0], thread_index);

      if (PREDICT_TRUE (uc0 != 0))
	{
	  udp_output_handle_packet (uc0, b[0], node, &next[0], is_ip4);
	}
      else
	{
	  b[0]->error = node->errors[UDP_ERROR_INVALID_CONNECTION];
	  next[0] = UDP_OUTPUT_NEXT_DROP;
	}

      b += 1;
      next += 1;
      n_left_from -= 1;
    }

  vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors);
  vlib_node_increment_counter (vm, udp_node_index (output, is_ip4),
			       UDP_ERROR_PKTS_SENT, frame->n_vectors);
  return frame->n_vectors;
}

VLIB_NODE_FN (udp4_output_node)
(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
{
  return udp46_output_inline (vm, node, from_frame, 1 /* is_ip4 */);
}

VLIB_NODE_FN (udp6_output_node)
(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
{
  return udp46_output_inline (vm, node, from_frame, 0 /* is_ip4 */);
}

VLIB_REGISTER_NODE (udp4_output_node) =
{
  .name = "udp4-output",
  .vector_size = sizeof (u32),
  .n_errors = UDP_N_ERROR,
  .protocol_hint = VLIB_NODE_PROTO_HINT_UDP,
  .error_counters = udp_output_error_counters,
  .n_next_nodes = UDP_OUTPUT_N_NEXT,
  .next_nodes = {
#define _(s, n) [UDP_OUTPUT_NEXT_##s] = n,
    foreach_udp4_output_next
#undef _
  },
  .format_buffer = format_udp_header,
  .format_trace = format_udp_tx_trace,
};

VLIB_REGISTER_NODE (udp6_output_node) =
{
  .name = "udp6-output",
  .vector_size = sizeof (u32),
  .n_errors = UDP_N_ERROR,
  .protocol_hint = VLIB_NODE_PROTO_HINT_UDP,
  .error_counters = udp_output_error_counters,
  .n_next_nodes = UDP_OUTPUT_N_NEXT,
  .next_nodes = {
#define _(s, n) [UDP_OUTPUT_NEXT_##s] = n,
    foreach_udp6_output_next
#undef _
  },
  .format_buffer = format_udp_header,
  .format_trace = format_udp_tx_trace,
};

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