/* Virtio helper functions from linux/tools/lguest/lguest.c
 *
 * Copyright (C) 1991-2016, the Linux Kernel authors
 * Copyright (c) 2016 Google Inc.
 *
 * Author:
 *  Rusty Russell <rusty@rustcorp.com.au>
 *  Kyle Milka <kmilka@google.com>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * The code from lguest.c has been modified for Akaros.
 *
 * Original linux/tools/lguest/lguest.c:
 *   https://github.com/torvalds/linux/blob/v4.5/tools/lguest/lguest.c
 *   most recent hash on the file as of v4.5 tag:
 *     e523caa601f4a7c2fa1ecd040db921baf7453798
 */

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <vmm/virtio.h>
#include <vmm/virtio_mmio.h>
#include <vmm/virtio_net.h>

#define VIRTIO_HEADER_SIZE	12

static int ctlfd;
static int etherfd;
static char data_path[128];
static char clone_path[64];

void net_init_fn(struct virtio_vq_dev *vqdev, int nic)
{
	char type[] = "connect -1";
	char buf[8];
	char addr_path[32];
	char addr_buf[3];
	int addr_fd;
	uint8_t addr_bytes;
	int num_read;
	int total_read = 0;

	snprintf(addr_path, sizeof(addr_path), "/net/ether%d/addr", nic);
	addr_fd = open(addr_path, O_RDONLY);
	if (addr_fd < 0)
		VIRTIO_DEV_ERRX(vqdev, "Bad addr_fd\n");

	for (int i = 0; i < ETH_ALEN; ++i) {
		assert(read(addr_fd, addr_buf, 2) == 2);
		addr_buf[2] = 0;
		addr_bytes = (uint8_t)(strtol(addr_buf, 0, 16));
		((struct virtio_net_config *)(vqdev->cfg))->mac[i] = addr_bytes;
		((struct virtio_net_config *)(vqdev->cfg_d))->mac[i] = addr_bytes;
	}

	snprintf(clone_path, sizeof(clone_path), "/net/ether%d/clone", nic);
	ctlfd = open(clone_path, O_RDWR);
	if (ctlfd < 0)
		VIRTIO_DEV_ERRX(vqdev, "%s", clone_path);

	do {
		num_read = read(ctlfd, buf + total_read, sizeof(buf) - total_read);
		total_read += num_read;
	} while (num_read > 0);

	etherfd = strtol(buf, 0, 10);
	if (etherfd < 0)
		VIRTIO_DEV_ERRX(vqdev, "bad etherfd %d (%s)", etherfd, buf);

	snprintf(data_path, sizeof(data_path),
	         "/net/ether%d/%d/data", nic, etherfd);

	if (write(ctlfd, type, sizeof(type)) != sizeof(type))
		VIRTIO_DEV_ERRX(vqdev, "write to ctlfd failed");
}

/* net_receiveq_fn receives packets for the guest through the virtio networking
 * device and the _vq virtio queue.
 */
void net_receiveq_fn(void *_vq)
{
	struct virtio_vq *vq = _vq;
	uint32_t head;
	uint32_t olen, ilen;
	int num_read;
	struct iovec *iov;
	struct virtio_mmio_dev *dev = vq->vqdev->transport_dev;
	int fd;
	struct virtio_net_hdr_v1 *net_header;

	fd = open(data_path, O_RDWR);
	if (fd == -1)
		VIRTIO_DEV_ERRX(vq->vqdev, "Could not open data file for ether1.");

	if (!vq)
		VIRTIO_DEV_ERRX(vq->vqdev,
			"\n  %s:%d\n"
			"  Virtio device: (not sure which one): Error, device behavior.\n"
			"  The device must provide a valid virtio_vq as an argument to %s."
			, __FILE__, __LINE__, __func__);

	if (vq->qready == 0x0)
		VIRTIO_DEV_ERRX(vq->vqdev,
			"The service function for queue '%s' was launched before the driver set QueueReady to 0x1.",
			vq->name);

	iov = malloc(vq->qnum_max * sizeof(struct iovec));
	assert(iov != NULL);

	if (!dev->poke_guest) {
		free(iov);
		VIRTIO_DEV_ERRX(vq->vqdev,
		                "The 'poke_guest' function pointer was not set.");
	}

	for (;;) {
		head = virtio_next_avail_vq_desc(vq, iov, &olen, &ilen);
		if (olen) {
			free(iov);
			VIRTIO_DRI_ERRX(vq->vqdev,
				"The driver placed a device-readable buffer in the net device's receiveq.\n"
				"  See virtio-v1.0-cs04 s5.3.6.1 Device Operation");
		}

		/* For receive the virtio header is in iov[0], so we only want
		 * the packet to be read into iov[1] and above.
		 */
		num_read = readv(fd, iov + 1, ilen - 1);
		if (num_read < 0) {
			free(iov);
			VIRTIO_DEV_ERRX(vq->vqdev,
				"Encountered an error trying to read input from the ethernet device.");
		}

		/* See virtio spec virtio-v1.0-cs04 s5.1.6.3.2 Device Requirements:
		 * Setting Up Receive Buffers
		 *
		 * VIRTIO_NET_F_MRG_RXBUF is not currently negotiated.
		 * num_buffers will always be 1 if VIRTIO_NET_F_MRG_RXBUF is not
		 * negotiated.
		 */
		net_header = iov[0].iov_base;
		net_header->num_buffers = 1;
		virtio_add_used_desc(vq, head, num_read + VIRTIO_HEADER_SIZE);

		virtio_mmio_set_vring_irq(dev);
		dev->poke_guest(dev->vec);
	}
}

/* net_transmitq_fn transmits packets from the guest through the virtio
 * networking device through the _vq virtio queue.
 */
void net_transmitq_fn(void *_vq)
{
	struct virtio_vq *vq = _vq;
	uint32_t head;
	uint32_t olen, ilen;
	struct iovec *iov;
	struct virtio_mmio_dev *dev = vq->vqdev->transport_dev;
	void *stripped;
	int ret;
	int fd = open(data_path, O_RDWR);

	if (fd == -1)
		VIRTIO_DEV_ERRX(vq->vqdev, "Could not open data file for ether1.");

	iov = malloc(vq->qnum_max * sizeof(struct iovec));
	assert(iov != NULL);

	if (!dev->poke_guest) {
		free(iov);
		VIRTIO_DEV_ERRX(vq->vqdev,
		                "The 'poke_guest' function pointer was not set.");
	}

	for (;;) {
		head = virtio_next_avail_vq_desc(vq, iov, &olen, &ilen);

		if (ilen) {
			free(iov);
			VIRTIO_DRI_ERRX(vq->vqdev,
			                "The driver placed a device-writeable buffer in the network device's transmitq.\n"
		                    "  See virtio-v1.0-cs04 s5.3.6.1 Device Operation");
		}

		/* Strip off the virtio header (the first 12 bytes), as it is
		 * not a part of the actual ethernet frame.
		 */
		for (int i = 0; i < olen; i++) {
			stripped = iov[i].iov_base + VIRTIO_HEADER_SIZE;
			ret = write(fd, stripped, iov[i].iov_len - VIRTIO_HEADER_SIZE);
			assert(ret == iov[i].iov_len - VIRTIO_HEADER_SIZE);
		}

		virtio_add_used_desc(vq, head, 0);

		virtio_mmio_set_vring_irq(dev);
		dev->poke_guest(dev->vec);
	}
}
