/*
 * lldp.c - send LLDP frames
 *
 * Copyright (C) 2014 Holger Hans Peter Freyther
 */
#include <common.h>
#include <command.h>
#include <complete.h>
#include <net.h>


static int do_lldp(int argc, char **argv)
{
	static uint8_t lldp_mult[] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x0e };
	static char *lldp_packet, *data, *start;
	struct eth_device *edev = eth_get_current();
	struct ethernet *et;
	int ret;

	if (!edev)
		return -ENETDOWN;

	if (!is_valid_ether_addr(edev->ethaddr)) {
		char str[sizeof("xx:xx:xx:xx:xx:xx")];
		random_ether_addr(edev->ethaddr);
		ethaddr_to_string(edev->ethaddr, str);
		printf("warning: No MAC address set. Using random address %s\n", str);
		dev_set_param(&edev->dev, "ethaddr", str);
	}

	if (!lldp_packet) {
		lldp_packet = net_alloc_packet();
		if (!lldp_packet)
			return -ENOMEM;
	}

	et = (struct ethernet *)lldp_packet;
	memcpy(et->et_src, edev->ethaddr, 6);
	memcpy(et->et_dest, lldp_mult, 6);
	et->et_protlen = htons(0x88cc);

	data = start = lldp_packet + ETHER_HDR_SIZE;

	/* chassis id */
	*data++ = 0x02;
	*data++ = 0x06;
	*data++ = 0x05;
	*data++ = 0x00;
	*data++ = 0x00;
	*data++ = 0x00;
	*data++ = 0x00;
	*data++ = 0x00;

	/* port id */
	*data++ = 0x04;
	*data++ = 0x02;
	*data++ = 0x07;
	*data++ = 0x5A;

	/* TTL */
	*data++ = 0x06;
	*data++ = 0x02;
	*data++ = 0x00;
	*data++ = 0xb4;

	/* end */
	*data++ = 0x00;
	*data++ = 0x00;

	ret = eth_send(edev, lldp_packet, ETHER_HDR_SIZE + (data-start));
	if (ret)
		return ret;

	return 0;
}

BAREBOX_CMD_HELP_START(lldp)
BAREBOX_CMD_HELP_TEXT("Options:")
BAREBOX_CMD_HELP_END

BAREBOX_CMD_START(lldp)
	.cmd		= do_lldp,
	BAREBOX_CMD_DESC("Send LLDP multicast packet")
	BAREBOX_CMD_OPTS("[]")
	BAREBOX_CMD_GROUP(CMD_GRP_NET)
	BAREBOX_CMD_HELP(cmd_lldp_help)
	BAREBOX_CMD_COMPLETE(empty_complete)
BAREBOX_CMD_END
