/*
 * Copyright (c) 2015 Intel Corporation
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <logging/log.h>
LOG_MODULE_DECLARE(net_zperf_sample, LOG_LEVEL_DBG);

#include <zephyr.h>

#include <misc/printk.h>

#include <net/net_core.h>
#include <net/net_ip.h>
#include <net/net_pkt.h>

#include "zperf.h"
#include "zperf_internal.h"

static u8_t sample_packet[sizeof(struct zperf_udp_datagram) +
			  sizeof(struct zperf_client_hdr_v1) +
			  PACKET_SIZE_MAX];

static inline void zperf_upload_decode_stat(const struct shell *shell,
					    struct net_pkt *pkt,
					    struct zperf_results *results)
{
	NET_PKT_DATA_ACCESS_DEFINE(zperf_udp, struct zperf_udp_datagram);
	NET_PKT_DATA_ACCESS_DEFINE(zperf_stat, struct zperf_server_hdr);
	struct zperf_udp_datagram *hdr;
	struct zperf_server_hdr *stat;

	hdr = (struct zperf_udp_datagram *)
		net_pkt_get_data(pkt, &zperf_udp);
	if (!hdr) {
		shell_fprintf(shell, SHELL_WARNING,
			      "Network packet too short\n");
		return;
	}

	net_pkt_acknowledge_data(pkt, &zperf_udp);

	stat = (struct zperf_server_hdr *)
		net_pkt_get_data(pkt, &zperf_stat);
	if (!stat) {
		shell_fprintf(shell, SHELL_WARNING,
			      "Network packet too short\n");
		return;
	}

	results->nb_packets_rcvd = ntohl(stat->datagrams);
	results->nb_packets_lost = ntohl(stat->error_cnt);
	results->nb_packets_outorder = ntohl(stat->outorder_cnt);
	results->nb_bytes_sent = ntohl(stat->total_len2);
	results->time_in_us = ntohl(stat->stop_usec) +
		ntohl(stat->stop_sec) * USEC_PER_SEC;
	results->jitter_in_us = ntohl(stat->jitter2) +
		ntohl(stat->jitter1) * USEC_PER_SEC;
}

static void stat_received(struct net_context *context,
			  struct net_pkt *pkt,
			  union net_ip_header *ip_hdr,
			  union net_proto_header *proto_hdr,
			  int status,
			  void *user_data)
{
	struct net_pkt **stat = user_data;

	*stat = pkt;
}

static inline void zperf_upload_fin(const struct shell *shell,
				    struct net_context *context,
				    u32_t nb_packets,
				    u32_t end_time,
				    u32_t packet_size,
				    struct zperf_results *results)
{
	struct net_pkt *stat = NULL;
	struct zperf_udp_datagram *datagram;
	struct zperf_client_hdr_v1 *hdr;
	int loop = 2;
	int ret;

	while (!stat && loop-- > 0) {
		datagram = (struct zperf_udp_datagram *)sample_packet;

		/* Fill the packet header */
		datagram->id = htonl(-nb_packets);
		datagram->tv_sec = htonl(HW_CYCLES_TO_SEC(end_time));
		datagram->tv_usec = htonl(HW_CYCLES_TO_USEC(end_time) %
					  USEC_PER_SEC);

		hdr = (struct zperf_client_hdr_v1 *)(sample_packet +
						     sizeof(*datagram));

		/* According to iperf documentation (in include/Settings.hpp),
		 * if the flags == 0, then the other values are ignored.
		 * But even if the values in the header are ignored, try
		 * to set there some meaningful values.
		 */
		hdr->flags = 0;
		hdr->num_of_threads = htonl(1);
		hdr->port = 0;
		hdr->buffer_len = sizeof(sample_packet) -
			sizeof(*datagram) - sizeof(*hdr);
		hdr->bandwidth = 0;
		hdr->num_of_bytes = htonl(packet_size);

		/* Send the packet */
		ret = net_context_send(context, sample_packet, packet_size,
				       NULL, K_NO_WAIT, NULL);
		if (ret < 0) {
			shell_fprintf(shell, SHELL_WARNING,
				      "Failed to send the packet (%d)\n",
				      ret);
			continue;
		}

		/* Receive statistics */
		stat = NULL;

		ret = net_context_recv(context, stat_received,
				       K_SECONDS(2), &stat);
		if (ret == -ETIMEDOUT) {
			break;
		}
	}

	/* Decode statistics */
	if (stat) {
		zperf_upload_decode_stat(shell, stat, results);

		net_pkt_unref(stat);
	}

	/* Drain RX */
	while (stat) {
		stat = NULL;

		ret = net_context_recv(context, stat_received,
				       K_NO_WAIT, &stat);
		if (ret == -ETIMEDOUT) {
			break;
		}

		if (stat) {
			shell_fprintf(shell, SHELL_WARNING,
				      "Drain one spurious stat packet!\n");

			net_pkt_unref(stat);
		}
	}
}

void zperf_udp_upload(const struct shell *shell,
		      struct net_context *context,
		      int port,
		      unsigned int duration_in_ms,
		      unsigned int packet_size,
		      unsigned int rate_in_kbps,
		      struct zperf_results *results)
{
	u32_t packet_duration = (u32_t)(((u64_t) packet_size *
					       SEC_TO_HW_CYCLES(1) * 8U) /
					      (u64_t)(rate_in_kbps * 1024U));
	u32_t duration = MSEC_TO_HW_CYCLES(duration_in_ms);
	u32_t print_interval = SEC_TO_HW_CYCLES(1);
	u32_t delay = packet_duration;
	u32_t nb_packets = 0U;
	u32_t start_time, last_print_time, last_loop_time, end_time;

	if (packet_size > PACKET_SIZE_MAX) {
		shell_fprintf(shell, SHELL_WARNING,
			      "Packet size too large! max size: %u\n",
			      PACKET_SIZE_MAX);
		packet_size = PACKET_SIZE_MAX;
	} else if (packet_size < sizeof(struct zperf_udp_datagram)) {
		shell_fprintf(shell, SHELL_WARNING,
			      "Packet size set to the min size: %zu\n",
			      sizeof(struct zperf_udp_datagram));
		packet_size = sizeof(struct zperf_udp_datagram);
	}

	/* Start the loop */
	start_time = k_cycle_get_32();
	last_print_time = start_time;
	last_loop_time = start_time;

	(void)memset(sample_packet, 'z', sizeof(sample_packet));

	do {
		struct zperf_udp_datagram *datagram;
		struct zperf_client_hdr_v1 *hdr;
		u32_t loop_time;
		s32_t adjust;
		int ret;

		/* Timestamp */
		loop_time = k_cycle_get_32();

		/* Algorithm to maintain a given baud rate */
		if (last_loop_time != loop_time) {
			adjust = packet_duration - time_delta(last_loop_time,
							      loop_time);
		} else {
			/* It's the first iteration so no need for adjustment
			 */
			adjust = 0;
		}

		if (adjust >= 0 || -adjust < delay) {
			delay += adjust;
		} else {
			delay = 0U; /* delay should never be a negative value */
		}

		last_loop_time = loop_time;

		/* Fill the packet header */
		datagram = (struct zperf_udp_datagram *)sample_packet;

		datagram->id = htonl(nb_packets);
		datagram->tv_sec = htonl(HW_CYCLES_TO_SEC(loop_time));
		datagram->tv_usec =
			htonl(HW_CYCLES_TO_USEC(loop_time) % USEC_PER_SEC);

		hdr = (struct zperf_client_hdr_v1 *)(sample_packet +
						     sizeof(*datagram));
		hdr->flags = 0;
		hdr->num_of_threads = htonl(1);
		hdr->port = htonl(port);
		hdr->buffer_len = sizeof(sample_packet) -
			sizeof(*datagram) - sizeof(*hdr);
		hdr->bandwidth = htonl(rate_in_kbps);
		hdr->num_of_bytes = htonl(packet_size);

		/* Send the packet */
		ret = net_context_send(context, sample_packet, packet_size,
				       NULL, K_NO_WAIT, NULL);
		if (ret < 0) {
			shell_fprintf(shell, SHELL_WARNING,
				      "Failed to send the packet (%d)\n",
				      ret);
			break;
		} else {
			nb_packets++;
		}

		/* Print log every seconds */
		if (time_delta(last_print_time, loop_time) > print_interval) {
			shell_fprintf(shell, SHELL_WARNING,
				    "nb_packets=%u\tdelay=%u\tadjust=%d\n",
				    nb_packets, delay, adjust);
			last_print_time = loop_time;
		}

		/* Wait */
#if defined(CONFIG_ARCH_POSIX)
		k_busy_wait(K_MSEC(100));
#else
		while (time_delta(loop_time, k_cycle_get_32()) < delay) {
			k_yield();
		}
#endif

	} while (time_delta(start_time, last_loop_time) < duration);

	end_time = k_cycle_get_32();

	zperf_upload_fin(shell, context, nb_packets, end_time, packet_size,
			 results);

	/* Add result coming from the client */
	results->nb_packets_sent = nb_packets;
	results->client_time_in_us =
		HW_CYCLES_TO_USEC(time_delta(start_time, end_time));
	results->packet_size = packet_size;
}
