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

#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(net_lldp_sample, LOG_LEVEL_DBG);

#include <zephyr/zephyr.h>

#include <zephyr/zephyr.h>
#include <errno.h>

#include <zephyr/net/net_core.h>
#include <zephyr/net/net_l2.h>
#include <zephyr/net/net_if.h>
#include <zephyr/net/ethernet.h>

static struct lldp_system_name_tlv {
	uint16_t type_length;
	uint8_t name[4];
} __packed tlv = {
	.name = { 't', 'e', 's', 't' },
};

static void set_optional_tlv(struct net_if *iface)
{
	NET_DBG("");

	tlv.type_length = htons((LLDP_TLV_SYSTEM_NAME << 9) |
				((sizeof(tlv) - sizeof(uint16_t)) & 0x01ff));

	net_lldp_config_optional(iface, (uint8_t *)&tlv, sizeof(tlv));
}

/* User data for the interface callback */
struct ud {
	struct net_if *first;
	struct net_if *second;
	struct net_if *third;
};

static void iface_cb(struct net_if *iface, void *user_data)
{
	struct ud *ud = user_data;

	if (net_if_l2(iface) != &NET_L2_GET_NAME(ETHERNET)) {
		return;
	}

	if (!ud->first) {
		ud->first = iface;
		return;
	}

	if (!ud->second) {
		ud->second = iface;
		return;
	}

	if (!ud->third) {
		ud->third = iface;
		return;
	}
}

static int setup_iface(struct net_if *iface, const char *ipv6_addr,
		       const char *ipv4_addr, uint16_t vlan_tag)
{
	struct net_if_addr *ifaddr;
	struct in_addr addr4;
	struct in6_addr addr6;
	int ret;

	ret = net_eth_vlan_enable(iface, vlan_tag);
	if (ret < 0) {
		LOG_ERR("Cannot enable VLAN for tag %d (%d)", vlan_tag, ret);
	}

	if (net_addr_pton(AF_INET6, ipv6_addr, &addr6)) {
		LOG_ERR("Invalid address: %s", ipv6_addr);
		return -EINVAL;
	}

	ifaddr = net_if_ipv6_addr_add(iface, &addr6, NET_ADDR_MANUAL, 0);
	if (!ifaddr) {
		LOG_ERR("Cannot add %s to interface %p", ipv6_addr, iface);
		return -EINVAL;
	}

	if (net_addr_pton(AF_INET, ipv4_addr, &addr4)) {
		LOG_ERR("Invalid address: %s", ipv4_addr);
		return -EINVAL;
	}

	ifaddr = net_if_ipv4_addr_add(iface, &addr4, NET_ADDR_MANUAL, 0);
	if (!ifaddr) {
		LOG_ERR("Cannot add %s to interface %p", ipv4_addr, iface);
		return -EINVAL;
	}

	LOG_DBG("Interface %p VLAN tag %d setup done.", iface, vlan_tag);

	return 0;
}

static struct ud ud;

static int init_vlan(void)
{
	enum ethernet_hw_caps caps;
	int ret;

	(void)memset(&ud, 0, sizeof(ud));

	net_if_foreach(iface_cb, &ud);

	caps = net_eth_get_hw_capabilities(ud.first);
	if (!(caps & ETHERNET_HW_VLAN)) {
		LOG_DBG("Interface %p does not support %s", ud.first, "VLAN");
		return -ENOENT;
	}

	/* This sample has two VLANs. For the second one we need to manually
	 * create IP address for this test. But first the VLAN needs to be
	 * added to the interface so that IPv6 DAD can work properly.
	 */
	ret = setup_iface(ud.second,
			  CONFIG_NET_SAMPLE_IFACE2_MY_IPV6_ADDR,
			  CONFIG_NET_SAMPLE_IFACE2_MY_IPV4_ADDR,
			  CONFIG_NET_SAMPLE_IFACE2_VLAN_TAG);
	if (ret < 0) {
		return ret;
	}

	ret = setup_iface(ud.third,
			  CONFIG_NET_SAMPLE_IFACE3_MY_IPV6_ADDR,
			  CONFIG_NET_SAMPLE_IFACE3_MY_IPV4_ADDR,
			  CONFIG_NET_SAMPLE_IFACE3_VLAN_TAG);
	if (ret < 0) {
		return ret;
	}

	return 0;
}

static enum net_verdict parse_lldp(struct net_if *iface, struct net_pkt *pkt)
{
	LOG_DBG("iface %p Parsing LLDP, len %zu", iface, net_pkt_get_len(pkt));

	net_pkt_cursor_init(pkt);

	while (1) {
		uint16_t type_length;
		uint16_t length;
		uint8_t type;

		if (net_pkt_read_be16(pkt, &type_length)) {
			LOG_DBG("End LLDP DU TLV");
			break;
		}

		length = type_length & 0x1FF;
		type = (uint8_t)(type_length >> 9);

		/* Skip for now data */
		if (net_pkt_skip(pkt, length)) {
			LOG_DBG("");
			break;
		}

		switch (type) {
		case LLDP_TLV_CHASSIS_ID:
			LOG_DBG("Chassis ID");
			break;
		case LLDP_TLV_PORT_ID:
			LOG_DBG("Port ID");
			break;
		case LLDP_TLV_TTL:
			LOG_DBG("TTL");
			break;
		default:
			LOG_DBG("TLV Not parsed");
			break;
		}

		LOG_DBG("type_length %u type %u length %u",
			type_length, type, length);
	}

	/* Let stack to free the packet */
	return NET_DROP;
}

static int init_app(void)
{
	enum ethernet_hw_caps caps;
	int ret;

	ret = init_vlan();
	if (ret < 0) {
		LOG_WRN("Cannot setup VLAN (%d)", ret);
	}

	caps = net_eth_get_hw_capabilities(ud.first);
	if (!(caps & ETHERNET_LLDP)) {
		LOG_ERR("Interface %p does not support %s", ud.first, "LLDP");
		LOG_ERR("Cannot continue!");
		return -ENOENT;
	}

	set_optional_tlv(ud.first);
	net_lldp_register_callback(ud.first, parse_lldp);

	return 0;
}

void main(void)
{
	/* The application will setup VLAN but does nothing meaningful.
	 * The configuration will enable LLDP support so you should see
	 * LLDPDU messages sent to the network interface.
	 */
	init_app();
}
