/*
 * Copyright (c) 2006, 2017 Oracle and/or its affiliates. All rights reserved.
 *
 * This software is available to you under a choice of one of two
 * licenses.  You may choose to be licensed under the terms of the GNU
 * General Public License (GPL) Version 2, available from the file
 * COPYING in the main directory of this source tree, or the
 * OpenIB.org BSD license below:
 *
 *     Redistribution and use in source and binary forms, with or
 *     without modification, are permitted provided that the following
 *     conditions are met:
 *
 *      - Redistributions of source code must retain the above
 *        copyright notice, this list of conditions and the following
 *        disclaimer.
 *
 *      - Redistributions in binary form must reproduce the above
 *        copyright notice, this list of conditions and the following
 *        disclaimer in the documentation and/or other materials
 *        provided with the distribution.
 *
 * 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 <linux/kernel.h>
#include <linux/slab.h>
#include <net/tcp.h>

#include "rds.h"
#include "tcp.h"

static struct kmem_cache *rds_tcp_incoming_slab;

static void rds_tcp_inc_purge(struct rds_incoming *inc)
{
	struct rds_tcp_incoming *tinc;
	tinc = container_of(inc, struct rds_tcp_incoming, ti_inc);
	rdsdebug("purging tinc %p inc %p\n", tinc, inc);
	skb_queue_purge(&tinc->ti_skb_list);
}

void rds_tcp_inc_free(struct rds_incoming *inc)
{
	struct rds_tcp_incoming *tinc;
	tinc = container_of(inc, struct rds_tcp_incoming, ti_inc);
	rds_tcp_inc_purge(inc);
	rdsdebug("freeing tinc %p inc %p\n", tinc, inc);
	kmem_cache_free(rds_tcp_incoming_slab, tinc);
}

/*
 * this is pretty lame, but, whatever.
 */
int rds_tcp_inc_copy_to_user(struct rds_incoming *inc, struct iov_iter *to)
{
	struct rds_tcp_incoming *tinc;
	struct sk_buff *skb;
	int ret = 0;

	if (!iov_iter_count(to))
		goto out;

	tinc = container_of(inc, struct rds_tcp_incoming, ti_inc);

	skb_queue_walk(&tinc->ti_skb_list, skb) {
		unsigned long to_copy, skb_off;
		for (skb_off = 0; skb_off < skb->len; skb_off += to_copy) {
			to_copy = iov_iter_count(to);
			to_copy = min(to_copy, skb->len - skb_off);

			if (skb_copy_datagram_iter(skb, skb_off, to, to_copy))
				return -EFAULT;

			rds_stats_add(s_copy_to_user, to_copy);
			ret += to_copy;

			if (!iov_iter_count(to))
				goto out;
		}
	}
out:
	return ret;
}

/*
 * We have a series of skbs that have fragmented pieces of the congestion
 * bitmap.  They must add up to the exact size of the congestion bitmap.  We
 * use the skb helpers to copy those into the pages that make up the in-memory
 * congestion bitmap for the remote address of this connection.  We then tell
 * the congestion core that the bitmap has been changed so that it can wake up
 * sleepers.
 *
 * This is racing with sending paths which are using test_bit to see if the
 * bitmap indicates that their recipient is congested.
 */

static void rds_tcp_cong_recv(struct rds_connection *conn,
			      struct rds_tcp_incoming *tinc)
{
	struct sk_buff *skb;
	unsigned int to_copy, skb_off;
	unsigned int map_off;
	unsigned int map_page;
	struct rds_cong_map *map;
	int ret;

	/* catch completely corrupt packets */
	if (be32_to_cpu(tinc->ti_inc.i_hdr.h_len) != RDS_CONG_MAP_BYTES)
		return;

	map_page = 0;
	map_off = 0;
	map = conn->c_fcong;

	skb_queue_walk(&tinc->ti_skb_list, skb) {
		skb_off = 0;
		while (skb_off < skb->len) {
			to_copy = min_t(unsigned int, PAGE_SIZE - map_off,
					skb->len - skb_off);

			BUG_ON(map_page >= RDS_CONG_MAP_PAGES);

			/* only returns 0 or -error */
			ret = skb_copy_bits(skb, skb_off,
				(void *)map->m_page_addrs[map_page] + map_off,
				to_copy);
			BUG_ON(ret != 0);

			skb_off += to_copy;
			map_off += to_copy;
			if (map_off == PAGE_SIZE) {
				map_off = 0;
				map_page++;
			}
		}
	}

	rds_cong_map_updated(map, ~(u64) 0);
}

struct rds_tcp_desc_arg {
	struct rds_conn_path *conn_path;
	gfp_t gfp;
};

static int rds_tcp_data_recv(read_descriptor_t *desc, struct sk_buff *skb,
			     unsigned int offset, size_t len)
{
	struct rds_tcp_desc_arg *arg = desc->arg.data;
	struct rds_conn_path *cp = arg->conn_path;
	struct rds_tcp_connection *tc = cp->cp_transport_data;
	struct rds_tcp_incoming *tinc = tc->t_tinc;
	struct sk_buff *clone;
	size_t left = len, to_copy;

	rdsdebug("tcp data tc %p skb %p offset %u len %zu\n", tc, skb, offset,
		 len);

	/*
	 * tcp_read_sock() interprets partial progress as an indication to stop
	 * processing.
	 */
	while (left) {
		if (!tinc) {
			tinc = kmem_cache_alloc(rds_tcp_incoming_slab,
						arg->gfp);
			if (!tinc) {
				desc->error = -ENOMEM;
				goto out;
			}
			tc->t_tinc = tinc;
			rdsdebug("allocated tinc %p\n", tinc);
			rds_inc_path_init(&tinc->ti_inc, cp,
					  &cp->cp_conn->c_faddr);
			tinc->ti_inc.i_rx_lat_trace[RDS_MSG_RX_HDR] =
					local_clock();

			/*
			 * XXX * we might be able to use the __ variants when
			 * we've already serialized at a higher level.
			 */
			skb_queue_head_init(&tinc->ti_skb_list);
		}

		if (left && tc->t_tinc_hdr_rem) {
			to_copy = min(tc->t_tinc_hdr_rem, left);
			rdsdebug("copying %zu header from skb %p\n", to_copy,
				 skb);
			skb_copy_bits(skb, offset,
				      (char *)&tinc->ti_inc.i_hdr +
						sizeof(struct rds_header) -
						tc->t_tinc_hdr_rem,
				      to_copy);
			tc->t_tinc_hdr_rem -= to_copy;
			left -= to_copy;
			offset += to_copy;

			if (tc->t_tinc_hdr_rem == 0) {
				/* could be 0 for a 0 len message */
				tc->t_tinc_data_rem =
					be32_to_cpu(tinc->ti_inc.i_hdr.h_len);
				tinc->ti_inc.i_rx_lat_trace[RDS_MSG_RX_START] =
					local_clock();
			}
		}

		if (left && tc->t_tinc_data_rem) {
			to_copy = min(tc->t_tinc_data_rem, left);

			clone = pskb_extract(skb, offset, to_copy, arg->gfp);
			if (!clone) {
				desc->error = -ENOMEM;
				goto out;
			}

			skb_queue_tail(&tinc->ti_skb_list, clone);

			rdsdebug("skb %p data %p len %d off %u to_copy %zu -> "
				 "clone %p data %p len %d\n",
				 skb, skb->data, skb->len, offset, to_copy,
				 clone, clone->data, clone->len);

			tc->t_tinc_data_rem -= to_copy;
			left -= to_copy;
			offset += to_copy;
		}

		if (tc->t_tinc_hdr_rem == 0 && tc->t_tinc_data_rem == 0) {
			struct rds_connection *conn = cp->cp_conn;

			if (tinc->ti_inc.i_hdr.h_flags == RDS_FLAG_CONG_BITMAP)
				rds_tcp_cong_recv(conn, tinc);
			else
				rds_recv_incoming(conn, &conn->c_faddr,
						  &conn->c_laddr,
						  &tinc->ti_inc,
						  arg->gfp);

			tc->t_tinc_hdr_rem = sizeof(struct rds_header);
			tc->t_tinc_data_rem = 0;
			tc->t_tinc = NULL;
			rds_inc_put(&tinc->ti_inc);
			tinc = NULL;
		}
	}
out:
	rdsdebug("returning len %zu left %zu skb len %d rx queue depth %d\n",
		 len, left, skb->len,
		 skb_queue_len(&tc->t_sock->sk->sk_receive_queue));
	return len - left;
}

/* the caller has to hold the sock lock */
static int rds_tcp_read_sock(struct rds_conn_path *cp, gfp_t gfp)
{
	struct rds_tcp_connection *tc = cp->cp_transport_data;
	struct socket *sock = tc->t_sock;
	read_descriptor_t desc;
	struct rds_tcp_desc_arg arg;

	/* It's like glib in the kernel! */
	arg.conn_path = cp;
	arg.gfp = gfp;
	desc.arg.data = &arg;
	desc.error = 0;
	desc.count = 1; /* give more than one skb per call */

	tcp_read_sock(sock->sk, &desc, rds_tcp_data_recv);
	rdsdebug("tcp_read_sock for tc %p gfp 0x%x returned %d\n", tc, gfp,
		 desc.error);

	return desc.error;
}

/*
 * We hold the sock lock to serialize our rds_tcp_recv->tcp_read_sock from
 * data_ready.
 *
 * if we fail to allocate we're in trouble.. blindly wait some time before
 * trying again to see if the VM can free up something for us.
 */
int rds_tcp_recv_path(struct rds_conn_path *cp)
{
	struct rds_tcp_connection *tc = cp->cp_transport_data;
	struct socket *sock = tc->t_sock;
	int ret = 0;

	rdsdebug("recv worker path [%d] tc %p sock %p\n",
		 cp->cp_index, tc, sock);

	lock_sock(sock->sk);
	ret = rds_tcp_read_sock(cp, GFP_KERNEL);
	release_sock(sock->sk);

	return ret;
}

void rds_tcp_data_ready(struct sock *sk)
{
	void (*ready)(struct sock *sk);
	struct rds_conn_path *cp;
	struct rds_tcp_connection *tc;

	rdsdebug("data ready sk %p\n", sk);

	read_lock_bh(&sk->sk_callback_lock);
	cp = sk->sk_user_data;
	if (!cp) { /* check for teardown race */
		ready = sk->sk_data_ready;
		goto out;
	}

	tc = cp->cp_transport_data;
	ready = tc->t_orig_data_ready;
	rds_tcp_stats_inc(s_tcp_data_ready_calls);

	if (rds_tcp_read_sock(cp, GFP_ATOMIC) == -ENOMEM) {
		rcu_read_lock();
		if (!rds_destroy_pending(cp->cp_conn))
			queue_delayed_work(rds_wq, &cp->cp_recv_w, 0);
		rcu_read_unlock();
	}
out:
	read_unlock_bh(&sk->sk_callback_lock);
	ready(sk);
}

int rds_tcp_recv_init(void)
{
	rds_tcp_incoming_slab = kmem_cache_create("rds_tcp_incoming",
					sizeof(struct rds_tcp_incoming),
					0, 0, NULL);
	if (!rds_tcp_incoming_slab)
		return -ENOMEM;
	return 0;
}

void rds_tcp_recv_exit(void)
{
	kmem_cache_destroy(rds_tcp_incoming_slab);
}
