Files
RTLPlayground/rtl837x_lldp.c
Rob Emery 9b2bd7f1b8 The tick rate has been changed now so we'll have to approximate
timing with ticks

Fixing up the log_to_phys_port assignment

2000 is about every 10 seconds, so scaling up to once every 30ish

Removing the attempt to block lldp frames,
This does not work however the hard work has been done for us in
the #514 so we can borrow that work later on
2026-10-10 09:50:38 +01:00

162 lines
4.0 KiB
C

#pragma codeseg BANK3
#pragma constseg BANK3
#include "rtl837x_common.h"
#include "rtl837x_lldp.h"
#include "rtl837x_sfr.h"
#include "rtl837x_common.h"
#include "dhcp.h"
#include "uip.h"
#include "uip/uip.h"
#include "machine.h"
extern __xdata bool lldp_enabled;
extern __code const struct machine machine;
__xdata uint16_t lldp_ticks;
__xdata uint16_t lldp_logical_port_status = 0xffff;
void lldp_init(void) __banked
{
lldp_ticks = 0;
}
void lldp_tick(void) __banked
{
lldp_ticks++;
if (lldp_ticks < LLDP_TX_INTERVAL_TICKS)
return;
lldp_ticks = 0;
if(lldp_enabled == 1)
lldp_send();
}
//Outgoing LLDP packet.
struct lldp_pkt {
struct uip_eth_addr dst;
struct uip_eth_addr src;
struct rtl_tag rtl_tag;
uint16_t ether_type;
uint8_t payload[64];
};
#define LLDP_O ((__xdata struct lldp_pkt *)&uip_buf[RTL_FRAME_DESC_SIZE])
// The type is 7 bits and the length is 9 bits
// we can represent this as the 7 most significant
// bits of the type bit and leave the least significant
// bit as 0 always as we're not going to need 2^9 for
// the length at any point
#define LLDP_TYPE(value) (value << 1)
void lldp_send(void) __banked __reentrant
{
__xdata uint8_t *p;
uint8_t port_position;
lldp_set_addresses();
lldp_set_rtl_wrapper();
p = LLDP_O->payload;
//Chassis ID
*p++ = LLDP_TYPE(LLDP_CHASSIS_ID_TLV_TYPE);
*p++ = LLDP_CHASSIS_ID_TLV_LENGTH;
*p++ = LLDP_CHASSIS_ID_TLV_SUBTYPE;
memcpy(p, uip_ethaddr.addr, MAC_ADDR_LEN);
p += MAC_ADDR_LEN;
//Port ID
*p++ = LLDP_TYPE(LLDP_PORT_ID_TLV_TYPE);
*p++ = LLDP_PORT_ID_TLV_LENGTH;
*p++ = LLDP_PORT_ID_TLV_SUBTYPE;
port_position = (p-LLDP_O->payload);
*p++ = '0'; // filled in per port below
//TTL
*p++ = LLDP_TYPE(LLDP_TTL_TLV_TYPE);
*p++ = LLDP_TTL_TLV_LENGTH;
*p++ = 0x00; //padding
*p++ = LLDP_TTL_TTL_SECONDS;
p += lldp_sysname(p);
p += lldp_sysdesc(p);
// End of LLDPDU TLV
*p++ = 0x00; //padding
*p++ = 0x00; //padding
while (p < (LLDP_O->payload + LLDP_MIN_ETHERNET_PAYLOAD_LENGTH))
*p++ = 0x00;
/*
* uip_len is the Ethernet frame length excluding FCS.
*
* The frame consists of:
*
* dst mac
* src mac
* rtl_tag sizeof(struct rtl_tag)
* EtherType (2 bytes)
* payload (how far we've moved p pointer)
*/
uip_len = MAC_ADDR_LEN + MAC_ADDR_LEN + sizeof(struct rtl_tag) + LLDP_ETHERTYPE_LENGTH + (p - LLDP_O->payload);
for (uint8_t port = machine.min_port; port <= machine.max_port; port++) {
if ((1 << port) & lldp_logical_port_status) {
LLDP_O->payload[port_position] = '0' + machine.log_to_phys_port[port];
LLDP_O->rtl_tag.pmask = HTONS((uint16_t)1 << port);
tcpip_output();
}
}
}
void lldp_set_addresses(void) __banked {
// LLDP destination multicast addr: 01:80:c2:00:00:0e
memcpyc(LLDP_O->dst.addr, "\x01\x80\xc2\x00\x00\x0e", MAC_ADDR_LEN);
memcpy(LLDP_O->src.addr, uip_ethaddr.addr, MAC_ADDR_LEN);
}
void lldp_set_rtl_wrapper(void) __banked {
/*
* This is the RTL CPU tag, not the Ethernet EtherType.
* port 0 -> 0x0001
* port 1 -> 0x0002
* port 2 -> 0x0004
*/
LLDP_O->rtl_tag.tag = HTONS(RTL_FRAME_TAG_ID);
LLDP_O->rtl_tag.version = RTL_FRAME_TAG_VERSION;
LLDP_O->rtl_tag.reason = 0x00;
LLDP_O->rtl_tag.flags = HTONS(RTL_TAG_LEARN_DIS);
LLDP_O->ether_type = HTONS(LLDP_ETHERTYPE);
}
uint8_t lldp_sysname(__xdata uint8_t *p) __banked
{
uint8_t hostname_length = strlen_x(hostname);
*p++ = LLDP_TYPE(LLDP_SYSNAME_TLV_TYPE);
*p++ = hostname_length;
memcpy(p, hostname, hostname_length);
return hostname_length + 2;
}
uint8_t lldp_sysdesc(__xdata uint8_t *p) __banked
{
uint16_t machine_name_length = strlen(machine.machine_name);
*p++ = LLDP_TYPE(LLDP_SYSDESC_TLV_TYPE);
*p++ = machine_name_length;
memcpyc(p, machine.machine_name, machine_name_length);
return machine_name_length + 2;
}