/*
 * 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 */
	/* Chasis 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("\tCHASIS 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)
