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

#include <vnet/udp/udp_local.h>
#include <vnet/udp/udp_encap.h>
#include <vnet/fib/fib_table.h>
#include <vnet/ip/ip_types_api.h>
#include <vnet/udp/udp.h>

#include <vnet/format_fns.h>
#include <vnet/udp/udp.api_enum.h>
#include <vnet/udp/udp.api_types.h>

#define REPLY_MSG_ID_BASE udp_main.msg_id_base
#include <vlibapi/api_helper_macros.h>

static void
send_udp_encap_details (const udp_encap_t * ue, vl_api_registration_t * reg,
			u32 context)
{
  vl_api_udp_encap_details_t *mp;

  mp = vl_msg_api_alloc (sizeof (*mp));
  clib_memset (mp, 0, sizeof (*mp));
  mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_UDP_ENCAP_DETAILS);
  mp->context = context;

  if (FIB_PROTOCOL_IP4 == ue->ue_ip_proto)
    {
      clib_memcpy (&mp->udp_encap.src_ip.un.ip4,
		   &ue->ue_hdrs.ip4.ue_ip4.src_address, 4);
      clib_memcpy (&mp->udp_encap.dst_ip.un.ip4,
		   &ue->ue_hdrs.ip4.ue_ip4.dst_address, 4);
      mp->udp_encap.dst_ip.af = ip_address_family_encode (AF_IP4);
      mp->udp_encap.src_ip.af = ip_address_family_encode (AF_IP4);

      /* ports aren't byte swapped because they are stored in network
       * byte order */
      mp->udp_encap.src_port = ue->ue_hdrs.ip4.ue_udp.src_port;
      mp->udp_encap.dst_port = ue->ue_hdrs.ip4.ue_udp.dst_port;
    }
  else
    {
      clib_memcpy (&mp->udp_encap.src_ip.un.ip6,
		   &ue->ue_hdrs.ip6.ue_ip6.src_address, 16);
      clib_memcpy (&mp->udp_encap.dst_ip.un.ip6,
		   &ue->ue_hdrs.ip6.ue_ip6.dst_address, 16);
      mp->udp_encap.dst_ip.af = ip_address_family_encode (AF_IP6);
      mp->udp_encap.src_ip.af = ip_address_family_encode (AF_IP6);

      /* ports aren't byte swapped because they are stored in network
       * byte order */
      mp->udp_encap.src_port = ue->ue_hdrs.ip6.ue_udp.src_port;
      mp->udp_encap.dst_port = ue->ue_hdrs.ip6.ue_udp.dst_port;
    }

  mp->udp_encap.table_id =
    htonl (fib_table_get_table_id (ue->ue_fib_index, ue->ue_ip_proto));
  mp->udp_encap.id = htonl (ue - udp_encap_pool);

  vl_api_send_msg (reg, (u8 *) mp);
}

static void
vl_api_udp_encap_dump_t_handler (vl_api_udp_encap_dump_t *mp)
{
  vl_api_registration_t *reg;
  udp_encap_t *ue;

  reg = vl_api_client_index_to_registration (mp->client_index);
  if (!reg)
    return;

  /* *INDENT-OFF* */
  pool_foreach (ue, udp_encap_pool)
   {
    send_udp_encap_details(ue, reg, mp->context);
  }
  /* *INDENT-ON* */
}

static void
vl_api_udp_encap_add_t_handler (vl_api_udp_encap_add_t *mp)
{
  vl_api_udp_encap_add_reply_t *rmp;
  ip46_address_t src_ip, dst_ip;
  u32 fib_index, table_id;
  fib_protocol_t fproto;
  ip46_type_t itype;
  index_t uei;
  int rv = 0;

  uei = INDEX_INVALID;
  table_id = ntohl (mp->udp_encap.table_id);

  itype = ip_address_decode (&mp->udp_encap.src_ip, &src_ip);
  itype = ip_address_decode (&mp->udp_encap.dst_ip, &dst_ip);
  fproto = fib_proto_from_ip46 (itype);
  fib_index = fib_table_find (fproto, table_id);

  if (~0 == fib_index)
    {
      rv = VNET_API_ERROR_NO_SUCH_TABLE;
      goto done;
    }

  uei = udp_encap_add_and_lock (fproto, fib_index,
				&src_ip, &dst_ip,
				ntohs (mp->udp_encap.src_port),
				ntohs (mp->udp_encap.dst_port),
				UDP_ENCAP_FIXUP_NONE);

done:
  /* *INDENT-OFF* */
  REPLY_MACRO2 (VL_API_UDP_ENCAP_ADD_REPLY,
  ({
    rmp->id = ntohl (uei);
  }));
  /* *INDENT-ON* */

}

static void
vl_api_udp_encap_del_t_handler (vl_api_udp_encap_del_t *mp)
{
  vl_api_udp_encap_del_reply_t *rmp;
  int rv = 0;

  udp_encap_unlock (ntohl (mp->id));

  REPLY_MACRO (VL_API_UDP_ENCAP_DEL_REPLY);
}

u32
udp_api_decap_proto_to_index (vlib_main_t *vm,
			      vl_api_udp_decap_next_proto_t iproto)
{
  switch (iproto)
    {
    case UDP_API_DECAP_PROTO_IP4:
      return vlib_get_node_by_name (vm, (u8 *) "ip4-input")->index;
    case UDP_API_DECAP_PROTO_IP6:
      return vlib_get_node_by_name (vm, (u8 *) "ip6-input")->index;
    case UDP_API_DECAP_PROTO_MPLS:
      return vlib_get_node_by_name (vm, (u8 *) "mpls-input")->index;
    }
  return ~0;
}

static void
vl_api_udp_decap_add_del_t_handler (vl_api_udp_decap_add_del_t *mp)
{
  vl_api_udp_decap_add_del_reply_t *rmp;
  vlib_main_t *vm = vlib_get_main ();
  int rv = 0;

  if (mp->is_add)
    {
      u32 node_index =
	udp_api_decap_proto_to_index (vm, ntohl (mp->udp_decap.next_proto));
      if (node_index == ~0)
	rv = VNET_API_ERROR_INVALID_PROTOCOL;
      else
	udp_register_dst_port (vm, ntohs (mp->udp_decap.port), node_index,
			       mp->udp_decap.is_ip4);
    }
  else
    udp_unregister_dst_port (vm, ntohs (mp->udp_decap.port),
			     mp->udp_decap.is_ip4);
  REPLY_MACRO (VL_API_UDP_DECAP_ADD_DEL_REPLY);
}

#include <vnet/udp/udp.api.c>
static clib_error_t *
udp_api_hookup (vlib_main_t * vm)
{
  /*
   * Set up the (msg_name, crc, message-id) table
   */
  REPLY_MSG_ID_BASE = setup_message_id_table ();

  return 0;
}

VLIB_API_INIT_FUNCTION (udp_api_hookup);

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