/*
 * Copyright (c) 2020 DENX Software Engineering GmbH
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include <net/socket.h>
#include <net/net_core.h>
#include <net/net_l2.h>
#include <net/net_if.h>
#include <net/socket.h>
#include <net/ethernet.h>
#include <net/lldp.h>
#include <errno.h>

#include <logging/log.h>
#include "main.h"

/* Loglevel of dsa_lldp function */
LOG_MODULE_DECLARE(net_dsa_lldp_sample, CONFIG_NET_DSA_LOG_LEVEL);

#define LLDP_SYSTEM_NAME_SIZE 24
#define LLDP_ETHER_TYPE 0x88CC
#define LLDP_INPUT_DATA_BUF_SIZE 512
#define DSA_BUF_SIZ 128
int dsa_lldp_send(struct net_if *iface, struct instance_data *pd,
		  uint16_t lan, int src_port, int origin_port, int cmd,
		  struct eth_addr *origin_addr)
{
	int ret, len;
	char buffer[DSA_BUF_SIZ], sys_name[LLDP_SYSTEM_NAME_SIZE];
	struct sockaddr_ll dst;
	struct ethernet_context *ctx = net_if_l2_data(iface);
	struct net_eth_hdr *eth_hdr = (struct net_eth_hdr *) buffer;
	uint8_t *p = &buffer[sizeof(struct net_eth_hdr)];
	uint8_t *pb = p;

	lan = ctx->dsa_port_idx;

	dst.sll_ifindex = net_if_get_by_iface(iface);
	/* Construct the Ethernet header */
	memset(buffer, 0, DSA_BUF_SIZ);
	/* Ethernet header */
	/* Take MAC address assigned to LAN port */
	memcpy(eth_hdr->src.addr, net_if_get_link_addr(iface)->addr, ETH_ALEN);
	eth_hdr->dst.addr[0] = MCAST_DEST_MAC0;
	eth_hdr->dst.addr[1] = MCAST_DEST_MAC1;
	eth_hdr->dst.addr[2] = MCAST_DEST_MAC2;
	eth_hdr->dst.addr[3] = MCAST_DEST_MAC3;
	eth_hdr->dst.addr[4] = MCAST_DEST_MAC4;
	eth_hdr->dst.addr[5] = MCAST_DEST_MAC5;

	/* Ethertype field */
	eth_hdr->type = htons(LLDP_ETHER_TYPE);

	/* LLDP packet data */
	/* Chassis ID */
	dsa_buf_write_be16((LLDP_TLV_CHASSIS_ID << 9) | (ETH_ALEN + 1), &p);
	*p++ = 4; /* subtype */
	memcpy(p, net_if_get_link_addr(iface)->addr, ETH_ALEN);
	p += ETH_ALEN;

	/* PORT ID */
	dsa_buf_write_be16((LLDP_TLV_PORT_ID << 9) | (ETH_ALEN + 1), &p);
	*p++ = 3; /* subtype */
	memcpy(p, net_if_get_link_addr(iface)->addr, ETH_ALEN);
	p += ETH_ALEN;

	/* TTL ID */
	dsa_buf_write_be16((LLDP_TLV_TTL << 9) | 2, &p);
	*p++ = 0; /* TTL field is 2 bytes long */
	*p++ = 120;

	/* SYSTEM NAME */
	memset(sys_name, 0, sizeof(sys_name));
	sprintf(sys_name, "ip_k66f LAN:%d", lan);
	dsa_buf_write_be16((LLDP_TLV_SYSTEM_NAME << 9) | strlen(sys_name), &p);
	memcpy(p, sys_name, strlen(sys_name));
	p += strlen(sys_name);

	len = sizeof(struct net_eth_hdr) + (p - pb);
	ret = sendto(pd->sock, buffer, len, 0, (const struct sockaddr *)&dst,
		     sizeof(struct sockaddr_ll));
	if (ret < 0) {
		LOG_ERR("Failed to send, errno %d", errno);
	}

	return 0;
}

void dsa_lldp_print_info(uint8_t *lldp_p, uint8_t lanid)
{
	uint16_t tl, length;
	uint8_t type, subtype;
	uint8_t *p, t1, t2;
	char t[LLDP_INPUT_DATA_BUF_SIZE];

	LOG_INF("LLDP pkt recv -> lan%d", lanid);
	do {
		/* In-buffer data is stored as big endian */
		t1 = *lldp_p++;
		t2 = *lldp_p++;
		tl = (uint16_t) t1 << 8 | t2;

		/* Get type and length */
		type = tl >> 9;
		length = tl & 0x1FF;

		switch (type) {
		case LLDP_TLV_CHASSIS_ID:
		case LLDP_TLV_PORT_ID:
			/* Extract subtype */
			subtype = *lldp_p++;
			length--;
			break;
		}

		p = lldp_p;

		switch (type) {
		case LLDP_TLV_END_LLDPDU:
			return;
		case LLDP_TLV_CHASSIS_ID:
			LOG_INF("\tCHASSIS ID:\t%02x:%02x:%02x:%02x:%02x:%02x",
				p[0], p[1], p[2], p[3], p[4], p[5]);
			break;
		case LLDP_TLV_PORT_ID:
			LOG_INF("\tPORT ID:\t%02x:%02x:%02x:%02x:%02x:%02x",
				p[0], p[1], p[2], p[3], p[4], p[5]);
			break;
		case LLDP_TLV_TTL:
			/* TTL field has 2 bytes in BE */
			LOG_INF("\tTTL:\t\t%ds", (uint16_t) p[0] << 8 | p[1]);
			break;
		case LLDP_TLV_SYSTEM_NAME:
			memset(t, 0, length + 1);
			memcpy(t, p, length);
			LOG_INF("\tSYSTEM NAME:\t%s", log_strdup(t));
			break;
		}
		lldp_p += length;
	} while (1);
}

int dsa_lldp_recv(struct net_if *iface, struct instance_data *pd,
		  uint16_t *lan, int *origin_port,
		  struct eth_addr *origin_addr)
{
	struct ethernet_context *ctx = net_if_l2_data(iface);
	struct net_eth_hdr *eth_hdr =
		(struct net_eth_hdr *) pd->recv_buffer;
	uint8_t *lldp_p = &pd->recv_buffer[sizeof(struct net_eth_hdr)];
	int received;

	*lan = ctx->dsa_port_idx;

	/* Receive data */
	received = recv(pd->sock, pd->recv_buffer,
			sizeof(pd->recv_buffer), 0);
	if (received < 0) {
		LOG_ERR("RAW : recv error %d", errno);
		return -1;
	}

	if (eth_hdr->type != 0xCC88) {
		LOG_ERR("Wrong LLDP packet type value [0x%x]", eth_hdr->type);
		return -1;
	}

	dsa_lldp_print_info(lldp_p, *lan);
	return 0;
}

DSA_THREAD(1, dsa_lldp_recv, dsa_lldp_send)
DSA_THREAD(2, dsa_lldp_recv, dsa_lldp_send)
DSA_THREAD(3, dsa_lldp_recv, dsa_lldp_send)
