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

/**
 * @file
 *
 * Network loopback interface implementation.
 */

#define LOG_MODULE_NAME netlo
#define LOG_LEVEL CONFIG_NET_LOOPBACK_LOG_LEVEL

#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(LOG_MODULE_NAME);

#include <zephyr/net/net_pkt.h>
#include <zephyr/net_buf.h>
#include <zephyr/net/net_ip.h>
#include <zephyr/net/net_if.h>
#include <zephyr/net/loopback.h>

#include <zephyr/net/dummy.h>

/* Allow network tests to control the IP addresses swapping */
#if defined(CONFIG_NET_TEST)
static bool loopback_dont_swap_addresses;

void loopback_enable_address_swap(bool swap_addresses)
{
	loopback_dont_swap_addresses = !swap_addresses;
}
#endif /* CONFIG_NET_TEST */

int loopback_dev_init(const struct device *dev)
{
	ARG_UNUSED(dev);

	return 0;
}

static void loopback_init(struct net_if *iface)
{
	struct net_if_addr *ifaddr;

	/* RFC 7042, s.2.1.1. address to use in documentation */
	net_if_set_link_addr(iface, "\x00\x00\x5e\x00\x53\xff", 6,
			     NET_LINK_DUMMY);

	if (IS_ENABLED(CONFIG_NET_IPV4)) {
		struct in_addr ipv4_loopback = INADDR_LOOPBACK_INIT;
		struct in_addr netmask = { { { 255, 0, 0, 0 } } };

		ifaddr = net_if_ipv4_addr_add(iface, &ipv4_loopback,
					      NET_ADDR_AUTOCONF, 0);
		if (!ifaddr) {
			LOG_ERR("Failed to register IPv4 loopback address");
		}

		net_if_ipv4_set_netmask_by_addr(iface, &ipv4_loopback, &netmask);
	}

	if (IS_ENABLED(CONFIG_NET_IPV6)) {
		struct in6_addr ipv6_loopback = IN6ADDR_LOOPBACK_INIT;

		ifaddr = net_if_ipv6_addr_add(iface, &ipv6_loopback,
					      NET_ADDR_AUTOCONF, 0);
		if (!ifaddr) {
			LOG_ERR("Failed to register IPv6 loopback address");
		}
	}
}

#ifdef CONFIG_NET_LOOPBACK_SIMULATE_PACKET_DROP
static float loopback_packet_drop_ratio = 0.0f;
static float loopback_packet_drop_state = 0.0f;
static int loopback_packet_dropped_count;

int loopback_set_packet_drop_ratio(float ratio)
{
	if (ratio < 0.0f || ratio > 1.0f) {
		return -EINVAL;
	}
	loopback_packet_drop_ratio = ratio;
	return 0;
}

int loopback_get_num_dropped_packets(void)
{
	return loopback_packet_dropped_count;
}

#endif

static int loopback_send(const struct device *dev, struct net_pkt *pkt)
{
	struct net_pkt *cloned;
	int res;

	ARG_UNUSED(dev);

#ifdef CONFIG_NET_LOOPBACK_SIMULATE_PACKET_DROP
	/* Drop packets based on the loopback_packet_drop_ratio
	 * a ratio of 0.2 will drop one every 5 packets
	 */
	loopback_packet_drop_state += loopback_packet_drop_ratio;
	if (loopback_packet_drop_state >= 1.0f) {
		/* Administrate we dropped a packet */
		loopback_packet_drop_state -= 1.0f;
		loopback_packet_dropped_count++;
		return 0;
	}
#endif

	if (!pkt->frags) {
		LOG_ERR("No data to send");
		return -ENODATA;
	}

	/* We should simulate normal driver meaning that if the packet is
	 * properly sent (which is always in this driver), then the packet
	 * must be dropped. This is very much needed for TCP packets where
	 * the packet is reference counted in various stages of sending.
	 */
	cloned = net_pkt_rx_clone(pkt, K_MSEC(100));
	if (!cloned) {
		res = -ENOMEM;
		goto out;
	}

	/* We need to swap the IP addresses because otherwise
	 * the packet will be dropped.
	 *
	 * Some of the network tests require that addresses are not swapped so allow
	 * the test to control this remotely.
	 */
	if (!COND_CODE_1(CONFIG_NET_TEST, (loopback_dont_swap_addresses), (false))) {
		if (net_pkt_family(pkt) == AF_INET6) {
			net_ipv6_addr_copy_raw(NET_IPV6_HDR(cloned)->src,
					       NET_IPV6_HDR(pkt)->dst);
			net_ipv6_addr_copy_raw(NET_IPV6_HDR(cloned)->dst,
					       NET_IPV6_HDR(pkt)->src);
		} else {
			net_ipv4_addr_copy_raw(NET_IPV4_HDR(cloned)->src,
					       NET_IPV4_HDR(pkt)->dst);
			net_ipv4_addr_copy_raw(NET_IPV4_HDR(cloned)->dst,
					       NET_IPV4_HDR(pkt)->src);
		}
	}

	res = net_recv_data(net_pkt_iface(cloned), cloned);
	if (res < 0) {
		LOG_ERR("Data receive failed.");
	}

out:
	/* Let the receiving thread run now */
	k_yield();

	return res;
}

static struct dummy_api loopback_api = {
	.iface_api.init = loopback_init,

	.send = loopback_send,
};

NET_DEVICE_INIT(loopback, "lo",
		loopback_dev_init, NULL, NULL, NULL,
		CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
		&loopback_api, DUMMY_L2,
		NET_L2_GET_CTX_TYPE(DUMMY_L2), CONFIG_NET_LOOPBACK_MTU);
