/*
 * Copyright (c) 2015-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.
 */
/*
 * ip/udp_pg: UDP packet-generator interface
 *
 * Copyright (c) 2008 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/pg/pg.h>
#include <vnet/ip/ip.h>		/* for unformat_udp_udp_port */
#include <vnet/udp/udp.h>

#define UDP_PG_EDIT_LENGTH (1 << 0)
#define UDP_PG_EDIT_CHECKSUM (1 << 1)

always_inline void
udp_pg_edit_function_inline (pg_main_t * pg,
			     pg_stream_t * s,
			     pg_edit_group_t * g,
			     u32 * packets, u32 n_packets, u32 flags)
{
  vlib_main_t *vm = vlib_get_main ();
  u32 ip_offset, udp_offset;

  udp_offset = g->start_byte_offset;
  ip_offset = (g - 1)->start_byte_offset;

  while (n_packets >= 1)
    {
      vlib_buffer_t *p0;
      ip4_header_t *ip0;
      udp_header_t *udp0;
      u32 udp_len0;

      p0 = vlib_get_buffer (vm, packets[0]);
      n_packets -= 1;
      packets += 1;

      ip0 = (void *) (p0->data + ip_offset);
      udp0 = (void *) (p0->data + udp_offset);
      udp_len0 = vlib_buffer_length_in_chain (vm, p0) - udp_offset;

      if (flags & UDP_PG_EDIT_LENGTH)
	udp0->length = clib_host_to_net_u16 (udp_len0);
      else
	udp_len0 = clib_host_to_net_u16 (udp0->length);

      /* Initialize checksum with header. */
      if (flags & UDP_PG_EDIT_CHECKSUM)
	{
	  ip_csum_t sum0;

	  sum0 = clib_mem_unaligned (&ip0->src_address, u64);

	  sum0 = ip_csum_with_carry
	    (sum0, clib_host_to_net_u32 (udp_len0 + (ip0->protocol << 16)));

	  /* Invalidate possibly old checksum. */
	  udp0->checksum = 0;

	  sum0 =
	    ip_incremental_checksum_buffer (vm, p0, udp_offset, udp_len0,
					    sum0);

	  sum0 = ~ip_csum_fold (sum0);

	  /* Zero checksum means checksumming disabled. */
	  sum0 = sum0 != 0 ? sum0 : 0xffff;

	  udp0->checksum = sum0;
	}
    }
}

static void
udp_pg_edit_function (pg_main_t * pg,
		      pg_stream_t * s,
		      pg_edit_group_t * g, u32 * packets, u32 n_packets)
{
  switch (g->edit_function_opaque)
    {
    case UDP_PG_EDIT_LENGTH:
      udp_pg_edit_function_inline (pg, s, g, packets, n_packets,
				   UDP_PG_EDIT_LENGTH);
      break;

    case UDP_PG_EDIT_CHECKSUM:
      udp_pg_edit_function_inline (pg, s, g, packets, n_packets,
				   UDP_PG_EDIT_CHECKSUM);
      break;

    case UDP_PG_EDIT_CHECKSUM | UDP_PG_EDIT_LENGTH:
      udp_pg_edit_function_inline (pg, s, g, packets, n_packets,
				   UDP_PG_EDIT_CHECKSUM | UDP_PG_EDIT_LENGTH);
      break;

    default:
      ASSERT (0);
      break;
    }
}

typedef struct
{
  pg_edit_t src_port, dst_port;
  pg_edit_t length;
  pg_edit_t checksum;
} pg_udp_header_t;

static inline void
pg_udp_header_init (pg_udp_header_t * p)
{
  /* Initialize fields that are not bit fields in the IP header. */
#define _(f) pg_edit_init (&p->f, udp_header_t, f);
  _(src_port);
  _(dst_port);
  _(length);
  _(checksum);
#undef _
}

uword
unformat_pg_udp_header (unformat_input_t * input, va_list * args)
{
  pg_stream_t *s = va_arg (*args, pg_stream_t *);
  pg_udp_header_t *p;
  u32 group_index;

  p = pg_create_edit_group (s, sizeof (p[0]), sizeof (udp_header_t),
			    &group_index);
  pg_udp_header_init (p);

  /* Defaults. */
  p->checksum.type = PG_EDIT_UNSPECIFIED;
  p->length.type = PG_EDIT_UNSPECIFIED;

  if (!unformat (input, "UDP: %U -> %U",
		 unformat_pg_edit,
		 unformat_tcp_udp_port, &p->src_port,
		 unformat_pg_edit, unformat_tcp_udp_port, &p->dst_port))
    goto error;

  /* Parse options. */
  while (1)
    {
      if (unformat (input, "length %U",
		    unformat_pg_edit, unformat_pg_number, &p->length))
	;

      else if (unformat (input, "checksum %U",
			 unformat_pg_edit, unformat_pg_number, &p->checksum))
	;

      /* Can't parse input: try next protocol level. */
      else
	break;
    }

  {
    ip_main_t *im = &ip_main;
    u16 dst_port;
    tcp_udp_port_info_t *pi;

    /* For the pg format of applications over UDP local */
    udp_dst_port_info_t *pi2 = NULL;

    pi = 0;
    if (p->dst_port.type == PG_EDIT_FIXED)
      {
	dst_port = pg_edit_get_value (&p->dst_port, PG_EDIT_LO);
	pi = ip_get_tcp_udp_port_info (im, dst_port);
	pi2 = udp_get_dst_port_info (&udp_main, dst_port, UDP_IP4);
	if (!pi2)
	  pi2 = udp_get_dst_port_info (&udp_main, dst_port, UDP_IP6);
      }

    if (pi && pi->unformat_pg_edit
	&& unformat_user (input, pi->unformat_pg_edit, s))
      ;
    else if (pi2 && pi2->unformat_pg_edit
	     && unformat_user (input, pi2->unformat_pg_edit, s))
      ;
    else if (!unformat_user (input, unformat_pg_payload, s))
      goto error;

    p = pg_get_edit_group (s, group_index);
    if (p->checksum.type == PG_EDIT_UNSPECIFIED
	|| p->length.type == PG_EDIT_UNSPECIFIED)
      {
	pg_edit_group_t *g = pg_stream_get_group (s, group_index);
	g->edit_function = udp_pg_edit_function;
	g->edit_function_opaque = 0;
	if (p->checksum.type == PG_EDIT_UNSPECIFIED)
	  g->edit_function_opaque |= UDP_PG_EDIT_CHECKSUM;
	if (p->length.type == PG_EDIT_UNSPECIFIED)
	  g->edit_function_opaque |= UDP_PG_EDIT_LENGTH;
      }

    return 1;
  }

error:
  /* Free up any edits we may have added. */
  pg_free_edit_group (s);
  return 0;
}


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