/*
 * l2_bvi.c : layer 2 Bridged Virtual Interface
 *
 * Copyright (c) 2013 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 <vnet/l2/l2_fwd.h>
#include <vnet/l2/l2_flood.h>
#include <vnet/l2/l2_bvi.h>

/* Allocated BVI instances */
static uword *l2_bvi_instances;

/* Call the L2 nodes that need the ethertype mapping */
void
l2bvi_register_input_type (vlib_main_t * vm,
			   ethernet_type_t type, u32 node_index)
{
  l2fwd_register_input_type (vm, type, node_index);
  l2flood_register_input_type (vm, type, node_index);
}

static u8 *
format_bvi_name (u8 * s, va_list * args)
{
  u32 dev_instance = va_arg (*args, u32);
  return format (s, "bvi%d", dev_instance);
}

static clib_error_t *
bvi_admin_up_down (vnet_main_t * vnm, u32 hw_if_index, u32 flags)
{
  u32 hw_flags = (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ?
    VNET_HW_INTERFACE_FLAG_LINK_UP : 0;
  vnet_hw_interface_set_flags (vnm, hw_if_index, hw_flags);
  return 0;
}

static clib_error_t *
bvi_mac_change (vnet_hw_interface_t * hi,
		const u8 * old_address, const u8 * mac_address)
{
  l2input_interface_mac_change (hi->sw_if_index, old_address, mac_address);

  return (NULL);
}

VNET_DEVICE_CLASS (bvi_device_class) = {
  .name = "BVI",
  .format_device_name = format_bvi_name,
  .admin_up_down_function = bvi_admin_up_down,
  .mac_addr_change_function = bvi_mac_change,
};

/*
 * Maintain a bitmap of allocated bvi instance numbers.
 */
#define BVI_MAX_INSTANCE		(16 * 1024)

static u32
bvi_instance_alloc (u32 want)
{
  /*
   * Check for dynamically allocated instance number.
   */
  if (~0 == want)
    {
      u32 bit;

      bit = clib_bitmap_first_clear (l2_bvi_instances);
      if (bit >= BVI_MAX_INSTANCE)
	{
	  return ~0;
	}
      l2_bvi_instances = clib_bitmap_set (l2_bvi_instances, bit, 1);
      return bit;
    }

  /*
   * In range?
   */
  if (want >= BVI_MAX_INSTANCE)
    {
      return ~0;
    }

  /*
   * Already in use?
   */
  if (clib_bitmap_get (l2_bvi_instances, want))
    {
      return ~0;
    }

  /*
   * Grant allocation request.
   */
  l2_bvi_instances = clib_bitmap_set (l2_bvi_instances, want, 1);

  return want;
}

static int
bvi_instance_free (u32 instance)
{
  if (instance >= BVI_MAX_INSTANCE)
    {
      return -1;
    }

  if (clib_bitmap_get (l2_bvi_instances, instance) == 0)
    {
      return -1;
    }

  l2_bvi_instances = clib_bitmap_set (l2_bvi_instances, instance, 0);
  return 0;
}

int
l2_bvi_create (u32 user_instance,
	       const mac_address_t * mac_in, u32 * sw_if_indexp)
{
  vnet_main_t *vnm = vnet_get_main ();
  vlib_main_t *vm = vlib_get_main ();
  vnet_eth_interface_registration_t eir = {};
  u32 instance, hw_if_index, slot;
  vnet_hw_interface_t *hw_if;
  mac_address_t mac;

  ASSERT (sw_if_indexp);

  *sw_if_indexp = (u32) ~ 0;

  /*
   * Allocate a bvi instance.  Either select on dynamically
   * or try to use the desired user_instance number.
   */
  instance = bvi_instance_alloc (user_instance);
  if (instance == ~0)
    {
      return VNET_API_ERROR_INVALID_REGISTRATION;
    }

  /*
   * Default MAC address (b0b0:0000:0000 + instance) is allocated
   * if zero mac_address is configured. Otherwise, user-configurable MAC
   * address is programmed on the bvi interface.
   */
  if (mac_address_is_zero (mac_in))
    {
      u8 bytes[6] = {
	[0] = 0xb0,
	[1] = 0xb0,
	[5] = instance,
      };
      mac_address_from_bytes (&mac, bytes);
    }
  else
    {
      mac_address_copy (&mac, mac_in);
    }

  eir.dev_class_index = bvi_device_class.index;
  eir.dev_instance = instance;
  eir.address = mac.bytes;
  hw_if_index = vnet_eth_register_interface (vnm, &eir);

  hw_if = vnet_get_hw_interface (vnm, hw_if_index);

  slot = vlib_node_add_named_next_with_slot (vm, hw_if->tx_node_index,
					     "l2-input", 0);
  ASSERT (slot == 0);

  {
    vnet_sw_interface_t *si = vnet_get_hw_sw_interface (vnm, hw_if_index);
    *sw_if_indexp = si->sw_if_index;

    si->flood_class = VNET_FLOOD_CLASS_BVI;
  }

  return 0;
}

int
l2_bvi_delete (u32 sw_if_index)
{
  vnet_main_t *vnm = vnet_get_main ();

  if (pool_is_free_index (vnm->interface_main.sw_interfaces, sw_if_index))
    return VNET_API_ERROR_INVALID_SW_IF_INDEX;

  vnet_hw_interface_t *hw = vnet_get_sup_hw_interface (vnm, sw_if_index);
  if (hw == 0 || hw->dev_class_index != bvi_device_class.index)
    return VNET_API_ERROR_INVALID_SW_IF_INDEX;

  if (bvi_instance_free (hw->dev_instance) < 0)
    return VNET_API_ERROR_INVALID_SW_IF_INDEX;

  ethernet_delete_interface (vnm, hw->hw_if_index);

  return 0;
}

static clib_error_t *
l2_bvi_create_cli (vlib_main_t * vm,
		   unformat_input_t * input, vlib_cli_command_t * cmd)
{
  unformat_input_t _line_input, *line_input = &_line_input;
  u32 instance, sw_if_index;
  clib_error_t *error;
  mac_address_t mac;
  int rv;

  error = NULL;
  instance = sw_if_index = ~0;
  mac_address_set_zero (&mac);

  if (unformat_user (input, unformat_line_input, line_input))
    {
      while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
	{
	  if (unformat (line_input, "mac %U", unformat_mac_address_t, &mac))
	    ;
	  else if (unformat (line_input, "instance %d", &instance))
	    ;
	  else
	    {
	      error = clib_error_return (0, "unknown input: %U",
					 format_unformat_error, line_input);
	      break;
	    }
	}

      unformat_free (line_input);

      if (error)
	return error;
    }

  rv = l2_bvi_create (instance, &mac, &sw_if_index);

  if (rv)
    return clib_error_return (0, "BVI create failed");

  vlib_cli_output (vm, "%U\n", format_vnet_sw_if_index_name, vnet_get_main (),
		   sw_if_index);
  return 0;
}

/*?
 * Create a BVI interface. Optionally, a MAC Address can be
 * provided. If not provided, 0b:0b::00:00:00:<instance> will be used.
 *
 * @cliexpar
 * The following two command syntaxes are equivalent:
 * @cliexcmd{bvi create [mac <mac-addr>] [instance <instance>]}
 * Example of how to create a bvi interface:
 * @cliexcmd{bvi create}
?*/
VLIB_CLI_COMMAND (l2_bvi_create_command, static) = {
  .path = "bvi create",
  .short_help = "bvi create [mac <mac-addr>] [instance <instance>]",
  .function = l2_bvi_create_cli,
};

static clib_error_t *
l2_bvi_delete_cli (vlib_main_t * vm,
		   unformat_input_t * input, vlib_cli_command_t * cmd)
{
  vnet_main_t *vnm;
  u32 sw_if_index;
  int rv;

  vnm = vnet_get_main ();
  sw_if_index = ~0;

  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
    {
      if (unformat
	  (input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index))
	;
      else
	break;
    }

  if (~0 != sw_if_index)
    {
      rv = l2_bvi_delete (sw_if_index);

      if (rv)
	return clib_error_return (0, "BVI delete failed");
    }
  else
    return clib_error_return (0, "no such interface: %U",
			      format_unformat_error, input);

  return 0;
}

/*?
 * Delete a BVI interface.
 *
 * @cliexpar
 * The following two command syntaxes are equivalent:
 * @cliexcmd{bvi delete <interface>}
 * Example of how to create a bvi interface:
 * @cliexcmd{bvi delete bvi0}
?*/
VLIB_CLI_COMMAND (l2_bvi_delete_command, static) = {
  .path = "bvi delete",
  .short_help = "bvi delete <interface>",
  .function = l2_bvi_delete_cli,
};


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