/*
 * Copyright (c) 2011-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.
 */
/**
 * @file
 * @brief LLDP packet parsing implementation
 */
#include <vnet/lldp/lldp_node.h>
#include <vnet/lldp/lldp_protocol.h>
#include <vlibmemory/api.h>

typedef struct
{
  u32 hw_if_index;
  u8 chassis_id_len;
  u8 chassis_id_subtype;
  u8 portid_len;
  u8 portid_subtype;
  u16 ttl;
  u8 data[0];			/* this contains both chassis id (chassis_id_len bytes) and port
				   id (portid_len bytes) */
} lldp_intf_update_t;

static void
lldp_rpc_update_peer_cb (const lldp_intf_update_t * a)
{
  ASSERT (os_get_cpu_number () == 0);

  lldp_intf_t *n = lldp_get_intf (&lldp_main, a->hw_if_index);
  if (!n)
    {
      /* LLDP turned off for this interface, ignore the update */
      return;
    }
  const u8 *chassis_id = a->data;
  const u8 *portid = a->data + a->chassis_id_len;

  if (n->chassis_id)
    {
      _vec_len (n->chassis_id) = 0;
    }
  vec_add (n->chassis_id, chassis_id, a->chassis_id_len);
  n->chassis_id_subtype = a->chassis_id_subtype;
  if (n->port_id)
    {
      _vec_len (n->port_id) = 0;
    }
  vec_add (n->port_id, portid, a->portid_len);
  n->port_id_subtype = a->portid_subtype;
  n->ttl = a->ttl;
  n->last_heard = vlib_time_now (lldp_main.vlib_main);
}

static void
lldp_rpc_update_peer (u32 hw_if_index, const u8 * chid, u8 chid_len,
		      u8 chid_subtype, const u8 * portid,
		      u8 portid_len, u8 portid_subtype, u16 ttl)
{
  const size_t data_size =
    sizeof (lldp_intf_update_t) + chid_len + portid_len;
  u8 data[data_size];
  lldp_intf_update_t *u = (lldp_intf_update_t *) data;
  u->hw_if_index = hw_if_index;
  u->chassis_id_len = chid_len;
  u->chassis_id_subtype = chid_subtype;
  u->ttl = ttl;
  u->portid_len = portid_len;
  u->portid_subtype = portid_subtype;
  clib_memcpy (u->data, chid, chid_len);
  clib_memcpy (u->data + chid_len, portid, portid_len);
  vl_api_rpc_call_main_thread (lldp_rpc_update_peer_cb, data, data_size);
}

lldp_tlv_code_t
lldp_tlv_get_code (const lldp_tlv_t * tlv)
{
  return tlv->head.byte1 >> 1;
}

void
lldp_tlv_set_code (lldp_tlv_t * tlv, lldp_tlv_code_t code)
{
  tlv->head.byte1 = (tlv->head.byte1 & 1) + (code << 1);
}

u16
lldp_tlv_get_length (const lldp_tlv_t * tlv)
{
  return (((u16) (tlv->head.byte1 & 1)) << 8) + tlv->head.byte2;
}

void
lldp_tlv_set_length (lldp_tlv_t * tlv, u16 length)
{
  tlv->head.byte2 = length & ((1 << 8) - 1);
  if (length > (1 << 8) - 1)
    {
      tlv->head.byte1 |= 1;
    }
  else
    {
      tlv->head.byte1 &= (1 << 8) - 2;
    }
}

lldp_main_t lldp_main;

static int
lldp_packet_scan (u32 hw_if_index, const lldp_tlv_t * pkt)
{
  const lldp_tlv_t *tlv = pkt;

#define TLV_VIOLATES_PKT_BOUNDARY(pkt, tlv)                               \
  (((((u8 *)tlv) + sizeof (lldp_tlv_t)) > ((u8 *)pkt + vec_len (pkt))) || \
   ((((u8 *)tlv) + lldp_tlv_get_length (tlv)) > ((u8 *)pkt + vec_len (pkt))))

  /* first tlv is always chassis id, followed by port id and ttl tlvs */
  if (TLV_VIOLATES_PKT_BOUNDARY (pkt, tlv) ||
      LLDP_TLV_NAME (chassis_id) != lldp_tlv_get_code (tlv))
    {
      return LLDP_ERROR_BAD_TLV;
    }

  u16 l = lldp_tlv_get_length (tlv);
  if (l < STRUCT_SIZE_OF (lldp_chassis_id_tlv_t, subtype) +
      LLDP_MIN_CHASS_ID_LEN ||
      l > STRUCT_SIZE_OF (lldp_chassis_id_tlv_t, subtype) +
      LLDP_MAX_CHASS_ID_LEN)
    {
      return LLDP_ERROR_BAD_TLV;
    }

  u8 chid_subtype = ((lldp_chassis_id_tlv_t *) tlv)->subtype;
  u8 *chid = ((lldp_chassis_id_tlv_t *) tlv)->id;
  u8 chid_len = l - STRUCT_SIZE_OF (lldp_chassis_id_tlv_t, subtype);

  tlv = (lldp_tlv_t *) ((u8 *) tlv + STRUCT_SIZE_OF (lldp_tlv_t, head) + l);

  if (TLV_VIOLATES_PKT_BOUNDARY (pkt, tlv) ||
      LLDP_TLV_NAME (port_id) != lldp_tlv_get_code (tlv))
    {
      return LLDP_ERROR_BAD_TLV;
    }
  l = lldp_tlv_get_length (tlv);
  if (l < STRUCT_SIZE_OF (lldp_port_id_tlv_t, subtype) +
      LLDP_MIN_PORT_ID_LEN ||
      l > STRUCT_SIZE_OF (lldp_chassis_id_tlv_t, subtype) +
      LLDP_MAX_PORT_ID_LEN)
    {
      return LLDP_ERROR_BAD_TLV;
    }

  u8 portid_subtype = ((lldp_port_id_tlv_t *) tlv)->subtype;
  u8 *portid = ((lldp_port_id_tlv_t *) tlv)->id;
  u8 portid_len = l - STRUCT_SIZE_OF (lldp_port_id_tlv_t, subtype);

  tlv = (lldp_tlv_t *) ((u8 *) tlv + STRUCT_SIZE_OF (lldp_tlv_t, head) + l);

  if (TLV_VIOLATES_PKT_BOUNDARY (pkt, tlv) ||
      LLDP_TLV_NAME (ttl) != lldp_tlv_get_code (tlv))
    {
      return LLDP_ERROR_BAD_TLV;
    }
  l = lldp_tlv_get_length (tlv);
  if (l != STRUCT_SIZE_OF (lldp_ttl_tlv_t, ttl))
    {
      return LLDP_ERROR_BAD_TLV;
    }
  u16 ttl = ntohs (((lldp_ttl_tlv_t *) tlv)->ttl);
  tlv = (lldp_tlv_t *) ((u8 *) tlv + STRUCT_SIZE_OF (lldp_tlv_t, head) + l);
  while (!TLV_VIOLATES_PKT_BOUNDARY (pkt, tlv) &&
	 LLDP_TLV_NAME (pdu_end) != lldp_tlv_get_code (tlv))
    {
      switch (lldp_tlv_get_code (tlv))
	{
#define F(num, type, str)     \
  case LLDP_TLV_NAME (type):  \
    /* ignore optional TLV */ \
    break;
	  foreach_lldp_optional_tlv_type (F);
#undef F
	default:
	  return LLDP_ERROR_BAD_TLV;
	}
      tlv = (lldp_tlv_t *) ((u8 *) tlv + STRUCT_SIZE_OF (lldp_tlv_t, head) +
			    lldp_tlv_get_length (tlv));
    }
  /* last tlv is pdu_end */
  if (TLV_VIOLATES_PKT_BOUNDARY (pkt, tlv) ||
      LLDP_TLV_NAME (pdu_end) != lldp_tlv_get_code (tlv) ||
      0 != lldp_tlv_get_length (tlv))
    {
      return LLDP_ERROR_BAD_TLV;
    }
  lldp_rpc_update_peer (hw_if_index, chid, chid_len, chid_subtype, portid,
			portid_len, portid_subtype, ttl);
  return LLDP_ERROR_NONE;
}

lldp_intf_t *
lldp_get_intf (lldp_main_t * lm, u32 hw_if_index)
{
  uword *p = hash_get (lm->intf_by_hw_if_index, hw_if_index);

  if (p)
    {
      return pool_elt_at_index (lm->intfs, p[0]);
    }
  return NULL;
}

lldp_intf_t *
lldp_create_intf (lldp_main_t * lm, u32 hw_if_index)
{

  uword *p;
  lldp_intf_t *n;
  p = hash_get (lm->intf_by_hw_if_index, hw_if_index);

  if (p == 0)
    {
      pool_get (lm->intfs, n);
      memset (n, 0, sizeof (*n));
      n->hw_if_index = hw_if_index;
      hash_set (lm->intf_by_hw_if_index, n->hw_if_index, n - lm->intfs);
    }
  else
    {
      n = pool_elt_at_index (lm->intfs, p[0]);
    }
  return n;
}

/*
 * lldp input routine
 */
lldp_error_t
lldp_input (vlib_main_t * vm, vlib_buffer_t * b0, u32 bi0)
{
  lldp_main_t *lm = &lldp_main;
  lldp_error_t e;

  /* find our interface */
  vnet_sw_interface_t *sw_interface = vnet_get_sw_interface (lm->vnet_main,
							     vnet_buffer
							     (b0)->sw_if_index
							     [VLIB_RX]);
  lldp_intf_t *n = lldp_get_intf (lm, sw_interface->hw_if_index);

  if (!n)
    {
      /* lldp disabled on this interface, we're done */
      return LLDP_ERROR_DISABLED;
    }

  /* Actually scan the packet */
  e = lldp_packet_scan (sw_interface->hw_if_index,
			vlib_buffer_get_current (b0));

  return e;
}

/*
 * setup function
 */
static clib_error_t *
lldp_init (vlib_main_t * vm)
{
  clib_error_t *error;
  lldp_main_t *lm = &lldp_main;

  if ((error = vlib_call_init_function (vm, lldp_template_init)))
    return error;

  lm->vlib_main = vm;
  lm->vnet_main = vnet_get_main ();
  lm->msg_tx_hold = 4;		/* default value per IEEE 802.1AB-2009 */
  lm->msg_tx_interval = 30;	/* default value per IEEE 802.1AB-2009 */

  return 0;
}

VLIB_INIT_FUNCTION (lldp_init);

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