1 /*
2 * Copyright (c) 2020 DENX Software Engineering GmbH
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #ifndef __DSA_SAMPLE__
8 #define __DSA_SAMPLE__
9
10 #include <zephyr/kernel.h>
11 #include <errno.h>
12
13 #include <zephyr/net/net_core.h>
14 #include <zephyr/net/net_l2.h>
15 #include <zephyr/net/net_if.h>
16 #include <zephyr/net/socket.h>
17 #include <zephyr/net/ethernet.h>
18
19 #define MCAST_DEST_MAC0 0x01
20 #define MCAST_DEST_MAC1 0x80
21 #define MCAST_DEST_MAC2 0xc2
22 #define MCAST_DEST_MAC3 0x00
23 #define MCAST_DEST_MAC4 0x00
24 #define MCAST_DEST_MAC5 0x03
25
26 #define RECV_BUFFER_SIZE 1280
27 #define ETH_ALEN 6
28 #define PACKET_LEN 128
29
30 extern struct ud user_data_ifaces;
31
32 struct eth_addr {
33 uint8_t addr[ETH_ALEN]; /* origin hardware address */
34 };
35
36 struct instance_data {
37 char *if_name;
38 int sock;
39 char recv_buffer[RECV_BUFFER_SIZE];
40 };
41
42 /* User data for the interface callback */
43 struct ud {
44 struct net_if *lan[3];
45 struct net_if *master;
46 };
47
check_ll_ether_addr(const uint8_t * a,const uint8_t * b)48 static inline bool check_ll_ether_addr(const uint8_t *a, const uint8_t *b)
49 {
50 return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2]) |
51 (a[3] ^ b[3]) | (a[4] ^ b[4]) | (a[5] ^ b[5])) == 0;
52 }
53
dsa_buf_write_be16(uint16_t tl,uint8_t ** p)54 static inline void dsa_buf_write_be16(uint16_t tl, uint8_t **p)
55 {
56 uint8_t *v = (uint8_t *) &tl;
57 **p = v[1];
58 (*p)++;
59 **p = v[0];
60 (*p)++;
61 }
62
63 int start_slave_port_packet_socket(struct net_if *iface,
64 struct instance_data *pd);
65
66 enum net_verdict dsa_ll_addr_switch_cb(struct net_if *iface,
67 struct net_pkt *pkt);
68
69 #define CMD_DISCOVER 0
70 #define CMD_ACK 1
71 #define DSA_STACK_SIZE 4096
72 #define DSA_PRIORITY 5
73 #define DSA_THREAD_START_DELAY 4000
74
75 #define DSA_THREAD(ID, FN_RECV, FN_SEND) \
76 static void dsa_thread_##ID(void *t1, void *t2, void *t3); \
77 K_THREAD_DEFINE(dsa_tid_##ID, DSA_STACK_SIZE, \
78 dsa_thread_##ID, NULL, NULL, NULL, \
79 DSA_PRIORITY, 0, DSA_THREAD_START_DELAY); \
80 \
81 void dsa_thread_##ID(void *t1, void *t2, void *t3) \
82 { \
83 int origin_port, ret; \
84 uint16_t seq; \
85 struct eth_addr origin_addr; \
86 struct instance_data data; \
87 struct net_if *iface; \
88 \
89 iface = user_data_ifaces.lan[ID-1]; \
90 \
91 data.if_name = "lan"#ID; \
92 ret = start_slave_port_packet_socket(iface, &data); \
93 if (ret < 0) { \
94 LOG_ERR("start_slave_port_packet_socket failed %d", \
95 ret); \
96 return; \
97 } \
98 dsa_register_recv_callback(iface, \
99 dsa_ll_addr_switch_cb); \
100 \
101 LOG_INF("DSA -> eth/lan"#ID" idx: %d sock: %d", \
102 net_if_get_by_iface(iface), data.sock); \
103 do { \
104 ret = FN_RECV(iface, &data, &seq, \
105 &origin_port, &origin_addr); \
106 if (ret) { \
107 break; \
108 } \
109 ret = FN_SEND(iface, &data, \
110 seq, 0, origin_port, CMD_ACK, \
111 &origin_addr); \
112 if (ret) { \
113 break; \
114 } \
115 } while (true); \
116 }
117
118 #endif /* __DSA_SAMPLE__ */
119