/*
 *------------------------------------------------------------------
 * 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 <stdint.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <fcntl.h>
#include <vnet/devices/netmap/net_netmap.h>

#include <vlib/vlib.h>
#include <vlib/unix/unix.h>
#include <vnet/ethernet/ethernet.h>
#include <vnet/devices/netmap/netmap.h>

netmap_main_t netmap_main;

static u32
netmap_eth_flag_change (vnet_main_t * vnm, vnet_hw_interface_t * hi,
			u32 flags)
{
  /* nothing for now */
  return 0;
}

static clib_error_t *
netmap_fd_read_ready (clib_file_t * uf)
{
  vlib_main_t *vm = vlib_get_main ();
  netmap_main_t *nm = &netmap_main;
  u32 idx = uf->private_data;

  nm->pending_input_bitmap =
    clib_bitmap_set (nm->pending_input_bitmap, idx, 1);

  /* Schedule the rx node */
  vlib_node_set_interrupt_pending (vm, netmap_input_node.index);

  return 0;
}

static void
close_netmap_if (netmap_main_t * nm, netmap_if_t * nif)
{
  if (nif->clib_file_index != ~0)
    {
      clib_file_del (&file_main, file_main.file_pool + nif->clib_file_index);
      nif->clib_file_index = ~0;
    }
  else if (nif->fd > -1)
    close (nif->fd);

  if (nif->mem_region)
    {
      netmap_mem_region_t *reg = &nm->mem_regions[nif->mem_region];
      if (--reg->refcnt == 0)
	{
	  munmap (reg->mem, reg->region_size);
	  reg->region_size = 0;
	}
    }


  mhash_unset (&nm->if_index_by_host_if_name, nif->host_if_name,
	       &nif->if_index);
  vec_free (nif->host_if_name);
  vec_free (nif->req);

  memset (nif, 0, sizeof (*nif));
  pool_put (nm->interfaces, nif);
}

int
netmap_worker_thread_enable ()
{
  /* if worker threads are enabled, switch to polling mode */
  foreach_vlib_main ((
		       {
		       vlib_node_set_state (this_vlib_main,
					    netmap_input_node.index,
					    VLIB_NODE_STATE_POLLING);
		       }));

  return 0;
}

int
netmap_worker_thread_disable ()
{
  foreach_vlib_main ((
		       {
		       vlib_node_set_state (this_vlib_main,
					    netmap_input_node.index,
					    VLIB_NODE_STATE_INTERRUPT);
		       }));

  return 0;
}

int
netmap_create_if (vlib_main_t * vm, u8 * if_name, u8 * hw_addr_set,
		  u8 is_pipe, u8 is_master, u32 * sw_if_index)
{
  netmap_main_t *nm = &netmap_main;
  int ret = 0;
  netmap_if_t *nif = 0;
  u8 hw_addr[6];
  clib_error_t *error = 0;
  vnet_sw_interface_t *sw;
  vnet_main_t *vnm = vnet_get_main ();
  uword *p;
  struct nmreq *req = 0;
  netmap_mem_region_t *reg;
  vlib_thread_main_t *tm = vlib_get_thread_main ();
  int fd;

  p = mhash_get (&nm->if_index_by_host_if_name, if_name);
  if (p)
    return VNET_API_ERROR_SUBIF_ALREADY_EXISTS;

  fd = open ("/dev/netmap", O_RDWR);
  if (fd < 0)
    return VNET_API_ERROR_SUBIF_ALREADY_EXISTS;

  pool_get (nm->interfaces, nif);
  nif->if_index = nif - nm->interfaces;
  nif->fd = fd;
  nif->clib_file_index = ~0;

  vec_validate (req, 0);
  nif->req = req;
  req->nr_version = NETMAP_API;
  req->nr_flags = NR_REG_ALL_NIC;

  if (is_pipe)
    req->nr_flags = is_master ? NR_REG_PIPE_MASTER : NR_REG_PIPE_SLAVE;
  else
    req->nr_flags = NR_REG_ALL_NIC;

  req->nr_flags |= NR_ACCEPT_VNET_HDR;
  snprintf (req->nr_name, IFNAMSIZ, "%s", if_name);
  req->nr_name[IFNAMSIZ - 1] = 0;

  if (ioctl (nif->fd, NIOCREGIF, req))
    {
      ret = VNET_API_ERROR_NOT_CONNECTED;
      goto error;
    }

  nif->mem_region = req->nr_arg2;
  vec_validate (nm->mem_regions, nif->mem_region);
  reg = &nm->mem_regions[nif->mem_region];
  if (reg->region_size == 0)
    {
      reg->mem = mmap (NULL, req->nr_memsize, PROT_READ | PROT_WRITE,
		       MAP_SHARED, fd, 0);
      clib_warning ("mem %p", reg->mem);
      if (reg->mem == MAP_FAILED)
	{
	  ret = VNET_API_ERROR_NOT_CONNECTED;
	  goto error;
	}
      reg->region_size = req->nr_memsize;
    }
  reg->refcnt++;

  nif->nifp = NETMAP_IF (reg->mem, req->nr_offset);
  nif->first_rx_ring = 0;
  nif->last_rx_ring = 0;
  nif->first_tx_ring = 0;
  nif->last_tx_ring = 0;
  nif->host_if_name = if_name;
  nif->per_interface_next_index = ~0;

  if (tm->n_vlib_mains > 1)
    clib_spinlock_init (&nif->lockp);

  {
    clib_file_t template = { 0 };
    template.read_function = netmap_fd_read_ready;
    template.file_descriptor = nif->fd;
    template.private_data = nif->if_index;
    nif->clib_file_index = clib_file_add (&file_main, &template);
  }

  /*use configured or generate random MAC address */
  if (hw_addr_set)
    memcpy (hw_addr, hw_addr_set, 6);
  else
    {
      f64 now = vlib_time_now (vm);
      u32 rnd;
      rnd = (u32) (now * 1e6);
      rnd = random_u32 (&rnd);

      memcpy (hw_addr + 2, &rnd, sizeof (rnd));
      hw_addr[0] = 2;
      hw_addr[1] = 0xfe;
    }

  error = ethernet_register_interface (vnm, netmap_device_class.index,
				       nif->if_index, hw_addr,
				       &nif->hw_if_index,
				       netmap_eth_flag_change);

  if (error)
    {
      clib_error_report (error);
      ret = VNET_API_ERROR_SYSCALL_ERROR_1;
      goto error;
    }

  sw = vnet_get_hw_sw_interface (vnm, nif->hw_if_index);
  nif->sw_if_index = sw->sw_if_index;

  mhash_set_mem (&nm->if_index_by_host_if_name, if_name, &nif->if_index, 0);

  if (sw_if_index)
    *sw_if_index = nif->sw_if_index;

  if (tm->n_vlib_mains > 1 && pool_elts (nm->interfaces) == 1)
    netmap_worker_thread_enable ();

  return 0;

error:
  close_netmap_if (nm, nif);
  return ret;
}

int
netmap_delete_if (vlib_main_t * vm, u8 * host_if_name)
{
  vnet_main_t *vnm = vnet_get_main ();
  netmap_main_t *nm = &netmap_main;
  netmap_if_t *nif;
  uword *p;
  vlib_thread_main_t *tm = vlib_get_thread_main ();

  p = mhash_get (&nm->if_index_by_host_if_name, host_if_name);
  if (p == NULL)
    {
      clib_warning ("Host interface %s does not exist", host_if_name);
      return VNET_API_ERROR_SYSCALL_ERROR_1;
    }
  nif = pool_elt_at_index (nm->interfaces, p[0]);

  /* bring down the interface */
  vnet_hw_interface_set_flags (vnm, nif->hw_if_index, 0);

  ethernet_delete_interface (vnm, nif->hw_if_index);

  close_netmap_if (nm, nif);

  if (tm->n_vlib_mains > 1 && pool_elts (nm->interfaces) == 0)
    netmap_worker_thread_disable ();

  return 0;
}

static clib_error_t *
netmap_init (vlib_main_t * vm)
{
  netmap_main_t *nm = &netmap_main;
  vlib_thread_main_t *tm = vlib_get_thread_main ();
  vlib_thread_registration_t *tr;
  uword *p;

  memset (nm, 0, sizeof (netmap_main_t));

  nm->input_cpu_first_index = 0;
  nm->input_cpu_count = 1;

  /* find out which cpus will be used for input */
  p = hash_get_mem (tm->thread_registrations_by_name, "workers");
  tr = p ? (vlib_thread_registration_t *) p[0] : 0;

  if (tr && tr->count > 0)
    {
      nm->input_cpu_first_index = tr->first_index;
      nm->input_cpu_count = tr->count;
    }

  mhash_init_vec_string (&nm->if_index_by_host_if_name, sizeof (uword));

  vec_validate_aligned (nm->rx_buffers, tm->n_vlib_mains - 1,
			CLIB_CACHE_LINE_BYTES);

  return 0;
}

VLIB_INIT_FUNCTION (netmap_init);

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