blob: 72c46f73cef37ec9689151aafc39dcb5f2e18c5f [file] [log] [blame]
/*
* Copyright (c) 2020 DENX Software Engineering GmbH
* Copyright 2024 NXP
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __DSA_SAMPLE_LLDP__
#define __DSA_SAMPLE_LLDP__
#include "dsa.h"
#define MCAST_DEST_MAC0 0x01
#define MCAST_DEST_MAC1 0x80
#define MCAST_DEST_MAC2 0xc2
#define MCAST_DEST_MAC3 0x00
#define MCAST_DEST_MAC4 0x00
#define MCAST_DEST_MAC5 0x03
#define RECV_BUFFER_SIZE 1280
#define ETH_ALEN 6
#define PACKET_LEN 128
struct eth_addr {
uint8_t addr[ETH_ALEN]; /* origin hardware address */
};
struct instance_data {
char *if_name;
int sock;
char recv_buffer[RECV_BUFFER_SIZE];
};
static inline bool check_ll_ether_addr(const uint8_t *a, const uint8_t *b)
{
return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2]) | (a[3] ^ b[3]) | (a[4] ^ b[4]) |
(a[5] ^ b[5])) == 0;
}
static inline void dsa_buf_write_be16(uint16_t tl, uint8_t **p)
{
uint8_t *v = (uint8_t *)&tl;
**p = v[1];
(*p)++;
**p = v[0];
(*p)++;
}
int start_user_port_packet_socket(struct net_if *iface, struct instance_data *pd);
enum net_verdict dsa_ll_addr_switch_cb(struct net_if *iface, struct net_pkt *pkt);
void dsa_lldp(struct ud *user_data);
#define CMD_DISCOVER 0
#define CMD_ACK 1
#define DSA_STACK_SIZE 4096
#define DSA_PRIORITY 5
#define DSA_THREAD_START_DELAY 4000
#define DSA_THREAD(ID, FN_RECV, FN_SEND) \
static void dsa_thread_##ID(void *t1, void *t2, void *t3); \
K_THREAD_DEFINE(dsa_tid_##ID, DSA_STACK_SIZE, dsa_thread_##ID, NULL, NULL, NULL, \
DSA_PRIORITY, 0, DSA_THREAD_START_DELAY); \
\
void dsa_thread_##ID(void *t1, void *t2, void *t3) \
{ \
int origin_port, ret; \
uint16_t seq; \
struct eth_addr origin_addr; \
struct instance_data data; \
struct net_if *iface; \
\
iface = user_data.lan[ID - 1]; \
\
data.if_name = "lan" #ID; \
ret = start_user_port_packet_socket(iface, &data); \
if (ret < 0) { \
LOG_ERR("start_user_port_packet_socket failed %d", ret); \
return; \
} \
dsa_register_recv_callback(iface, dsa_ll_addr_switch_cb); \
\
LOG_INF("DSA -> eth/lan" #ID " idx: %d sock: %d", net_if_get_by_iface(iface), \
data.sock); \
do { \
ret = FN_RECV(iface, &data, &seq, &origin_port, &origin_addr); \
if (ret) { \
break; \
} \
ret = FN_SEND(iface, &data, seq, 0, origin_port, CMD_ACK, &origin_addr); \
if (ret) { \
break; \
} \
} while (true); \
}
#endif /* __DSA_SAMPLE_LLDP__ */