/* * 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__ */