1 /*
2 * Copyright 2025 NXP
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/logging/log.h>
8 LOG_MODULE_REGISTER(net_dsa_tag_netc, CONFIG_NET_DSA_LOG_LEVEL);
9
10 #include <zephyr/net/ethernet.h>
11 #include <zephyr/net/dsa_core.h>
12 #include "dsa_tag_netc.h"
13 #include "fsl_netc_tag.h"
14
15 /* tag is inserted after DMAC/SMAC fields */
16 struct dsa_tag_netc_to_host_header {
17 uint8_t dmac[NET_ETH_ADDR_LEN];
18 uint8_t smac[NET_ETH_ADDR_LEN];
19 netc_swt_tag_host_t tag;
20 };
21
22 struct dsa_tag_netc_to_port_header {
23 uint8_t dmac[NET_ETH_ADDR_LEN];
24 uint8_t smac[NET_ETH_ADDR_LEN];
25 netc_swt_tag_port_no_ts_t tag;
26 };
27
dsa_tag_netc_recv(struct net_if * iface,struct net_pkt * pkt)28 struct net_if *dsa_tag_netc_recv(struct net_if *iface, struct net_pkt *pkt)
29 {
30 struct ethernet_context *eth_ctx = net_if_l2_data(iface);
31 uint16_t header_len = sizeof(struct dsa_tag_netc_to_host_header);
32 struct dsa_tag_netc_to_host_header *header;
33 struct net_if *iface_dst = iface;
34 uint8_t *ptr;
35
36 if (pkt->frags->len < header_len) {
37 LOG_ERR("tag len error");
38 return iface_dst;
39 }
40
41 /* redirect to user port */
42 header = (struct dsa_tag_netc_to_host_header *)pkt->frags->data;
43 iface_dst = eth_ctx->dsa_switch_ctx->iface_user[header->tag.comTag.port];
44
45 /* drop tag */
46 ptr = net_buf_pull(pkt->frags, sizeof(netc_swt_tag_host_t));
47 for (int i = 0; i < (NET_ETH_ADDR_LEN * 2); i++) {
48 ptr[i] = *(uint8_t *)((uintptr_t)header + i);
49 }
50
51 return iface_dst;
52 }
53
dsa_tag_netc_xmit(struct net_if * iface,struct net_pkt * pkt)54 struct net_pkt *dsa_tag_netc_xmit(struct net_if *iface, struct net_pkt *pkt)
55 {
56 const struct device *dev = net_if_get_device(iface);
57 struct dsa_port_config *cfg = (struct dsa_port_config *)dev->config;
58 struct dsa_tag_netc_to_port_header *header;
59 struct net_buf *header_buf;
60
61 /* Allocate net_buf for header */
62 header_buf = net_buf_alloc_len(net_buf_pool_get(pkt->buffer->pool_id),
63 sizeof(*header), K_NO_WAIT);
64 if (!header_buf) {
65 LOG_ERR("Cannot allocate header buffer");
66 return NULL;
67 }
68
69 header_buf->len = sizeof(*header);
70
71 /* Fill the header */
72 header = (struct dsa_tag_netc_to_port_header *)header_buf->data;
73 memcpy(header, pkt->frags->data, NET_ETH_ADDR_LEN * 2);
74 header->tag.comTag.tpid = NETC_SWITCH_DEFAULT_ETHER_TYPE;
75 header->tag.comTag.subType = kNETC_TagToPortNoTs;
76 header->tag.comTag.type = kNETC_TagToPort;
77 header->tag.comTag.swtId = 1;
78 header->tag.comTag.port = cfg->port_idx;
79
80 /* Drop DMAC/SMAC on original frag */
81 net_buf_pull(pkt->frags, NET_ETH_ADDR_LEN * 2);
82
83 /* Insert header */
84 header_buf->frags = pkt->frags;
85 pkt->frags = header_buf;
86
87 net_pkt_cursor_init(pkt);
88 return pkt;
89 }
90