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

#include <vnet/span/span.h>

int
span_add_delete_entry (vlib_main_t * vm,
		       u32 src_sw_if_index, u32 dst_sw_if_index, u8 state)
{
  span_main_t *sm = &span_main;
  span_interface_t *si;
  u32 new_num_rx_mirror_ports, new_num_tx_mirror_ports;

  if (state > 3)
    return VNET_API_ERROR_UNIMPLEMENTED;

  if ((src_sw_if_index == ~0) || (dst_sw_if_index == ~0 && state > 0)
      || (src_sw_if_index == dst_sw_if_index))
    return VNET_API_ERROR_INVALID_INTERFACE;

  vnet_sw_interface_t *sw_if;

  sw_if = vnet_get_sw_interface (vnet_get_main (), src_sw_if_index);
  if (sw_if->type == VNET_SW_INTERFACE_TYPE_SUB)
    return VNET_API_ERROR_UNIMPLEMENTED;

  vec_validate_aligned (sm->interfaces, src_sw_if_index,
			CLIB_CACHE_LINE_BYTES);
  si = vec_elt_at_index (sm->interfaces, src_sw_if_index);

  si->rx_mirror_ports = clib_bitmap_set (si->rx_mirror_ports, dst_sw_if_index,
					 (state & 1) != 0);
  si->tx_mirror_ports = clib_bitmap_set (si->tx_mirror_ports, dst_sw_if_index,
					 (state & 2) != 0);

  new_num_rx_mirror_ports = clib_bitmap_count_set_bits (si->rx_mirror_ports);
  new_num_tx_mirror_ports = clib_bitmap_count_set_bits (si->tx_mirror_ports);

  if (new_num_rx_mirror_ports == 1 && si->num_rx_mirror_ports == 0)
    vnet_feature_enable_disable ("device-input", "span-input",
				 src_sw_if_index, 1, 0, 0);

  if (new_num_rx_mirror_ports == 0 && si->num_rx_mirror_ports == 1)
    vnet_feature_enable_disable ("device-input", "span-input",
				 src_sw_if_index, 0, 0, 0);

  if (new_num_rx_mirror_ports == 1 && si->num_rx_mirror_ports == 0)
    vnet_feature_enable_disable ("device-input", "span-output",
				 src_sw_if_index, 1, 0, 0);

  if (new_num_rx_mirror_ports == 0 && si->num_rx_mirror_ports == 1)
    vnet_feature_enable_disable ("device-input", "span-output",
				 src_sw_if_index, 0, 0, 0);

  si->num_rx_mirror_ports = new_num_rx_mirror_ports;
  si->num_tx_mirror_ports = new_num_tx_mirror_ports;

  if (dst_sw_if_index > sm->max_sw_if_index)
    sm->max_sw_if_index = dst_sw_if_index;

  return 0;
}

static clib_error_t *
set_interface_span_command_fn (vlib_main_t * vm,
			       unformat_input_t * input,
			       vlib_cli_command_t * cmd)
{
  span_main_t *sm = &span_main;
  u32 src_sw_if_index = ~0;
  u32 dst_sw_if_index = ~0;
  u8 state = 3;

  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
    {
      if (unformat (input, "%U", unformat_vnet_sw_interface,
		    sm->vnet_main, &src_sw_if_index))
	;
      else if (unformat (input, "destination %U", unformat_vnet_sw_interface,
			 sm->vnet_main, &dst_sw_if_index))
	;
      else if (unformat (input, "disable"))
	state = 0;
      else if (unformat (input, "rx"))
	state = 1;
      else if (unformat (input, "tx"))
	state = 2;
      else if (unformat (input, "both"))
	state = 3;
      else
	break;
    }

  int rv =
    span_add_delete_entry (vm, src_sw_if_index, dst_sw_if_index, state);
  if (rv == VNET_API_ERROR_INVALID_INTERFACE)
    return clib_error_return (0, "Invalid interface");
  return 0;
}

/* *INDENT-OFF* */
VLIB_CLI_COMMAND (set_interface_span_command, static) = {
  .path = "set interface span",
  .short_help = "set interface span <if-name> [disable | destination <if-name> [both|rx|tx]]",
  .function = set_interface_span_command_fn,
};
/* *INDENT-ON* */

static clib_error_t *
show_interfaces_span_command_fn (vlib_main_t * vm,
				 unformat_input_t * input,
				 vlib_cli_command_t * cmd)
{
  span_main_t *sm = &span_main;
  span_interface_t *si;
  vnet_main_t *vnm = &vnet_main;
  u8 header = 1;
  char *states[] = { "none", "rx", "tx", "both" };
  u8 *s = 0;

  /* *INDENT-OFF* */
  vec_foreach (si, sm->interfaces)
    if (si->num_rx_mirror_ports || si->num_tx_mirror_ports)
      {
	clib_bitmap_t *b;
	u32 i;
	b = clib_bitmap_dup_or (si->rx_mirror_ports, si->tx_mirror_ports);
	if (header)
	  {
	    vlib_cli_output (vm, "%-40s %s", "Source interface",
			     "Mirror interface (direction)");
	    header = 0;
	  }
	s = format (s, "%U", format_vnet_sw_if_index_name, vnm,
		    si - sm->interfaces);
	clib_bitmap_foreach (i, b, (
	  {
	    int state;
	    state = (clib_bitmap_get (si->rx_mirror_ports, i) +
		     clib_bitmap_get (si->tx_mirror_ports, i) * 2);

	    vlib_cli_output (vm, "%-40v %U (%s)", s,
			     format_vnet_sw_if_index_name, vnm, i,
			     states[state]);
	    vec_reset_length (s);
	  }));
	clib_bitmap_free (b);
      }
  /* *INDENT-ON* */
  vec_free (s);
  return 0;
}

/* *INDENT-OFF* */
VLIB_CLI_COMMAND (show_interfaces_span_command, static) = {
  .path = "show interfaces span",
  .short_help = "Shows SPAN mirror table",
  .function = show_interfaces_span_command_fn,
};
/* *INDENT-ON* */

static clib_error_t *
span_init (vlib_main_t * vm)
{
  span_main_t *sm = &span_main;

  sm->vlib_main = vm;
  sm->vnet_main = vnet_get_main ();

  return 0;
}

VLIB_INIT_FUNCTION (span_init);

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