/*
 * Copyright (c) 2018 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/feature/feature.h>
#include <vnet/ethernet/ethernet.h>

#ifndef CLIB_MARCH_VARIANT
int
vnet_sw_interface_stats_collect_enable_disable (u32 sw_if_index, u8 enable)
{
  ethernet_interface_t *eif;
  vnet_sw_interface_t *si;
  ethernet_main_t *em;
  vnet_main_t *vnm;

  vnm = vnet_get_main ();
  em = &ethernet_main;
  si = vnet_get_sw_interface (vnm, sw_if_index);

  /*
   * only ethernet HW interfaces are supported at this time
   */
  if (si->type != VNET_SW_INTERFACE_TYPE_HARDWARE)
    {
      return (VNET_API_ERROR_INVALID_VALUE);
    }

  eif = ethernet_get_interface (em, si->hw_if_index);

  if (!eif)
    {
      return (VNET_API_ERROR_FEATURE_DISABLED);
    }

  vnet_feature_enable_disable ("device-input", "stats-collect-rx",
			       sw_if_index, enable, 0, 0);
  vnet_feature_enable_disable ("interface-output", "stats-collect-tx",
			       sw_if_index, enable, 0, 0);

  return (0);
}
#endif /* CLIB_MARCH_VARIANT */

static u8 *
format_stats_collect_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 *);

  return s;
}

#define inc_counter(ctype, rx_tx)                               \
{                                                               \
}

static_always_inline uword
stats_collect_inline (vlib_main_t * vm,
		      vlib_node_runtime_t * node,
		      vlib_frame_t * frame, vlib_rx_or_tx_t rxtx)
{
  vnet_interface_counter_type_t ct;
  u32 n_left_from, *from, *to_next;
  u32 next_index;
  u32 sw_if_index = 0;
  u32 stats_n_packets[VNET_N_COMBINED_INTERFACE_COUNTER] = { 0 };
  u64 stats_n_bytes[VNET_N_COMBINED_INTERFACE_COUNTER] = { 0 };

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

  while (n_left_from > 0)
    {
      u32 n_left_to_next;

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

      while (n_left_from > 0 && n_left_to_next > 0)
	{
	  u32 bi0;
	  vlib_buffer_t *b0;
	  u32 next0 = 0;
	  int b0_ctype;

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

	  b0 = vlib_get_buffer (vm, bi0);
	  sw_if_index = vnet_buffer (b0)->sw_if_index[rxtx];

	  if (VLIB_RX == rxtx)
	    {
	      b0_ctype =
		eh_dst_addr_to_rx_ctype (vlib_buffer_get_current (b0));
	    }
	  else
	    {
	      b0_ctype =
		eh_dst_addr_to_tx_ctype (vlib_buffer_get_current (b0));
	    }

	  stats_n_bytes[b0_ctype] += vlib_buffer_length_in_chain (vm, b0);
	  stats_n_packets[b0_ctype] += 1;

	  vnet_feature_next (&next0, b0);

	  vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
					   n_left_to_next, bi0, next0);
	}

      if (VLIB_RX == rxtx)
	{
	  foreach_rx_combined_interface_counter (ct)
	  {
	    vlib_increment_combined_counter
	      (vnet_main.interface_main.combined_sw_if_counters + ct,
	       vlib_get_thread_index (),
	       sw_if_index, stats_n_packets[ct], stats_n_bytes[ct]);
	  }
	}
      else
	{
	  foreach_tx_combined_interface_counter (ct)
	  {
	    vlib_increment_combined_counter
	      (vnet_main.interface_main.combined_sw_if_counters + ct,
	       vlib_get_thread_index (),
	       sw_if_index, stats_n_packets[ct], stats_n_bytes[ct]);
	  }
	}

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

  return frame->n_vectors;
}

VLIB_NODE_FN (stats_collect_rx_node) (vlib_main_t * vm,
				      vlib_node_runtime_t * node,
				      vlib_frame_t * frame)
{
  return stats_collect_inline (vm, node, frame, VLIB_RX);
}

VLIB_NODE_FN (stats_collect_tx_node) (vlib_main_t * vm,
				      vlib_node_runtime_t * node,
				      vlib_frame_t * frame)
{
  return stats_collect_inline (vm, node, frame, VLIB_TX);
}

VLIB_REGISTER_NODE (stats_collect_rx_node) = {
  .vector_size = sizeof (u32),
  .format_trace = format_stats_collect_trace,
  .type = VLIB_NODE_TYPE_INTERNAL,
  .n_errors = 0,
  .n_next_nodes = 0,
  .name = "stats-collect-rx",
};

VLIB_REGISTER_NODE (stats_collect_tx_node) = {
  .vector_size = sizeof (u32),
  .format_trace = format_stats_collect_trace,
  .type = VLIB_NODE_TYPE_INTERNAL,
  .n_errors = 0,
  .n_next_nodes = 0,
  .name = "stats-collect-tx",
};

VNET_FEATURE_INIT (stats_collect_rx_node, static) = {
  .arc_name = "device-input",
  .node_name = "stats-collect-rx",
  .runs_before = VNET_FEATURES ("ethernet-input"),
};

VNET_FEATURE_INIT (stats_collect_tx_node, static) = {
  .arc_name = "interface-output",
  .node_name = "stats-collect-tx",
  .runs_before = VNET_FEATURES ("interface-output-arc-end"),
};


static clib_error_t *
stats_collect_init (vlib_main_t * vm)
{
  return 0;
}

VLIB_INIT_FUNCTION (stats_collect_init);


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