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