/*
 * Copyright (c) 2015 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.
 */
/*
 * hdlc.c: hdlc
 *
 * Copyright (c) 2010 Eliot Dresselhaus
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#include <vnet/vnet.h>
#include <vnet/hdlc/hdlc.h>

/* Global main structure. */
hdlc_main_t hdlc_main;

u8 * format_hdlc_protocol (u8 * s, va_list * args)
{
  hdlc_protocol_t p = va_arg (*args, u32);
  hdlc_main_t * pm = &hdlc_main;
  hdlc_protocol_info_t * pi = hdlc_get_protocol_info (pm, p);

  if (pi)
    s = format (s, "%s", pi->name);
  else
    s = format (s, "0x%04x", p);

  return s;
}

u8 * format_hdlc_header_with_length (u8 * s, va_list * args)
{
  hdlc_main_t * pm = &hdlc_main;
  hdlc_header_t * h = va_arg (*args, hdlc_header_t *);
  u32 max_header_bytes = va_arg (*args, u32);
  hdlc_protocol_t p = clib_net_to_host_u16 (h->protocol);
  uword indent, header_bytes;

  header_bytes = sizeof (h[0]);
  if (max_header_bytes != 0 && header_bytes > max_header_bytes)
    return format (s, "hdlc header truncated");

  indent = format_get_indent (s);

  s = format (s, "HDLC %U", format_hdlc_protocol, p);

  if (h->address != 0xff)
    s = format (s, ", address 0x%02x", h->address);
  if (h->control != 0x03)
    s = format (s, ", control 0x%02x", h->control);

  if (max_header_bytes != 0 && header_bytes > max_header_bytes)
    {
      hdlc_protocol_info_t * pi = hdlc_get_protocol_info (pm, p);
      vlib_node_t * node = vlib_get_node (pm->vlib_main, pi->node_index);
      if (node->format_buffer)
	s = format (s, "\n%U%U",
		    format_white_space, indent,
		    node->format_buffer, (void *) (h + 1),
		    max_header_bytes - header_bytes);
    }

  return s;
}

u8 * format_hdlc_header (u8 * s, va_list * args)
{
  hdlc_header_t * h = va_arg (*args, hdlc_header_t *);
  return format (s, "%U", format_hdlc_header_with_length, h, 0);
}

/* Returns hdlc protocol as an int in host byte order. */
uword
unformat_hdlc_protocol_host_byte_order (unformat_input_t * input,
				       va_list * args)
{
  u16 * result = va_arg (*args, u16 *);
  hdlc_main_t * pm = &hdlc_main;
  int p, i;

  /* Numeric type. */
  if (unformat (input, "0x%x", &p)
      || unformat (input, "%d", &p))
    {
      if (p >= (1 << 16))
	return 0;
      *result = p;
      return 1;
    }

  /* Named type. */
  if (unformat_user (input, unformat_vlib_number_by_name,
		     pm->protocol_info_by_name, &i))
    {
      hdlc_protocol_info_t * pi = vec_elt_at_index (pm->protocol_infos, i);
      *result = pi->protocol;
      return 1;
    }

  return 0;
}

uword
unformat_hdlc_protocol_net_byte_order (unformat_input_t * input,
				      va_list * args)
{
  u16 * result = va_arg (*args, u16 *);
  if (! unformat_user (input, unformat_hdlc_protocol_host_byte_order, result))
    return 0;
  *result = clib_host_to_net_u16 ((u16) *result);
  return 1;
}

uword
unformat_hdlc_header (unformat_input_t * input, va_list * args)
{
  u8 ** result = va_arg (*args, u8 **);
  hdlc_header_t _h, * h = &_h;
  u16 p;

  if (! unformat (input, "%U",
		  unformat_hdlc_protocol_host_byte_order, &p))
    return 0;

  h->address = 0xff;
  h->control = 0x03;
  h->protocol = clib_host_to_net_u16 (p);

  /* Add header to result. */
  {
    void * p;
    u32 n_bytes = sizeof (h[0]);

    vec_add2 (*result, p, n_bytes);
    clib_memcpy (p, h, n_bytes);
  }
  
  return 1;
}

static u8*
hdlc_build_rewrite (vnet_main_t * vnm,
		    u32 sw_if_index,
		    vnet_link_t link_type,
		    const void *dst_address)
{
  hdlc_header_t * h;
  u8* rewrite = NULL;
  hdlc_protocol_t protocol;

  switch (link_type) {
#define _(a,b) case VNET_LINK_##a: protocol = HDLC_PROTOCOL_##b; break
    _ (IP4, ip4);
    _ (IP6, ip6);
    _ (MPLS, mpls_unicast);
#undef _
  default:
      return (NULL);
  }

  vec_validate(rewrite, sizeof(*h)-1);
  h = (hdlc_header_t *)rewrite;
  h->address = 0x0f;
  h->control = 0x00;
  h->protocol = clib_host_to_net_u16 (protocol);
		     
  return (rewrite);
}

VNET_HW_INTERFACE_CLASS (hdlc_hw_interface_class) = {
  .name = "HDLC",
  .format_header = format_hdlc_header_with_length,
  .unformat_header = unformat_hdlc_header,
  .build_rewrite = hdlc_build_rewrite,
  .flags = VNET_HW_INTERFACE_CLASS_FLAG_P2P,
};

static void add_protocol (hdlc_main_t * pm,
			  hdlc_protocol_t protocol,
			  char * protocol_name)
{
  hdlc_protocol_info_t * pi;
  u32 i;

  vec_add2 (pm->protocol_infos, pi, 1);
  i = pi - pm->protocol_infos;

  pi->name = protocol_name;
  pi->protocol = protocol;
  pi->next_index = pi->node_index = ~0;

  hash_set (pm->protocol_info_by_protocol, protocol, i);
  hash_set_mem (pm->protocol_info_by_name, pi->name, i);
}

static clib_error_t * hdlc_init (vlib_main_t * vm)
{
  hdlc_main_t * pm = &hdlc_main;

  memset (pm, 0, sizeof (pm[0]));
  pm->vlib_main = vm;

  pm->protocol_info_by_name = hash_create_string (0, sizeof (uword));
  pm->protocol_info_by_protocol = hash_create (0, sizeof (uword));

#define _(n,s) add_protocol (pm, HDLC_PROTOCOL_##s, #s);
  foreach_hdlc_protocol
#undef _

  return vlib_call_init_function (vm, hdlc_input_init);
}

VLIB_INIT_FUNCTION (hdlc_init);

hdlc_main_t * hdlc_get_main (vlib_main_t * vm)
{
  vlib_call_init_function (vm, hdlc_init);
  return &hdlc_main;
}

