Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(C) 2025 Marvell International Ltd.
3 : : */
4 : :
5 : : #include <arpa/inet.h>
6 : : #include <sys/socket.h>
7 : :
8 : : #include <rte_ethdev.h>
9 : : #include <rte_ether.h>
10 : : #include <rte_graph_feature_arc_worker.h>
11 : : #include <rte_malloc.h>
12 : :
13 : : #include "rte_node_ip4_api.h"
14 : : #include "node_private.h"
15 : : #include "interface_tx_feature_priv.h"
16 : :
17 : : #define IF_TX_FEATURE_LAST_NEXT_INDEX(ctx) \
18 : : (((struct if_tx_feature_node_ctx *)ctx)->last_index)
19 : : /*
20 : : * @internal array for mapping port to next node index
21 : : */
22 : : struct if_tx_feature_node_main {
23 : : uint16_t next_index[RTE_MAX_ETHPORTS];
24 : : };
25 : :
26 : : struct if_tx_feature_node_ctx {
27 : : uint16_t last_index;
28 : : };
29 : :
30 : : static struct if_tx_feature_node_main *if_tx_feature_nm;
31 : :
32 : : int
33 : 0 : if_tx_feature_node_set_next(uint16_t port_id, uint16_t next_index)
34 : : {
35 [ # # ]: 0 : if (if_tx_feature_nm == NULL) {
36 : 0 : if_tx_feature_nm = rte_zmalloc(
37 : : "if_tx_feature_nm", sizeof(struct if_tx_feature_node_main),
38 : : RTE_CACHE_LINE_SIZE);
39 [ # # ]: 0 : if (if_tx_feature_nm == NULL)
40 : : return -ENOMEM;
41 : : }
42 : 0 : if_tx_feature_nm->next_index[port_id] = next_index;
43 : :
44 : 0 : return 0;
45 : : }
46 : :
47 : : static int
48 : 0 : if_tx_feature_node_init(const struct rte_graph *graph, struct rte_node *node)
49 : : {
50 : : RTE_SET_USED(graph);
51 : :
52 : : /* pkt_drop */
53 : 0 : IF_TX_FEATURE_LAST_NEXT_INDEX(node->ctx) = 0;
54 : :
55 : 0 : return 0;
56 : : }
57 : :
58 : : static uint16_t
59 : 0 : if_tx_feature_node_process(struct rte_graph *graph, struct rte_node *node,
60 : : void **objs, uint16_t nb_objs)
61 : : {
62 : : uint16_t held = 0, next0 = 0, next1 = 0, next2 = 0, next3 = 0;
63 : : struct rte_mbuf *mbuf0, *mbuf1, *mbuf2, *mbuf3, **pkts;
64 : : uint16_t last_spec = 0, fix_spec = 0;
65 : : void **to_next, **from;
66 : : rte_edge_t next_index;
67 : : uint16_t n_left_from;
68 : :
69 : : /* Speculative next */
70 : 0 : next_index = IF_TX_FEATURE_LAST_NEXT_INDEX(node->ctx);
71 : :
72 : : from = objs;
73 : : n_left_from = nb_objs;
74 : : pkts = (struct rte_mbuf **)objs;
75 : :
76 : 0 : to_next = rte_node_next_stream_get(graph, node, next_index, nb_objs);
77 [ # # ]: 0 : while (n_left_from > 4) {
78 [ # # ]: 0 : if (likely(n_left_from > 7)) {
79 : : /* Prefetch next mbuf */
80 : 0 : rte_prefetch0(objs[4]);
81 : 0 : rte_prefetch0(objs[5]);
82 : 0 : rte_prefetch0(objs[6]);
83 : 0 : rte_prefetch0(objs[7]);
84 : : }
85 : 0 : mbuf0 = pkts[0];
86 : 0 : mbuf1 = pkts[1];
87 : 0 : mbuf2 = pkts[2];
88 : 0 : mbuf3 = pkts[3];
89 : 0 : pkts += 4;
90 : 0 : n_left_from -= 4;
91 : :
92 : : /* port-tx node starts from next edge 1*/
93 : 0 : next0 = if_tx_feature_nm->next_index[mbuf0->port];
94 : 0 : next1 = if_tx_feature_nm->next_index[mbuf1->port];
95 : 0 : next2 = if_tx_feature_nm->next_index[mbuf2->port];
96 : 0 : next3 = if_tx_feature_nm->next_index[mbuf3->port];
97 : :
98 : 0 : fix_spec = (next_index ^ next0) | (next_index ^ next1) |
99 : : (next_index ^ next2) | (next_index ^ next3);
100 : :
101 [ # # ]: 0 : if (unlikely(fix_spec)) {
102 : : /* Copy things successfully speculated till now */
103 [ # # ]: 0 : rte_memcpy(to_next, from,
104 : : last_spec * sizeof(from[0]));
105 : 0 : from += last_spec;
106 : 0 : to_next += last_spec;
107 : 0 : held += last_spec;
108 : : last_spec = 0;
109 : :
110 [ # # ]: 0 : if (next0 == next_index) {
111 : 0 : to_next[0] = from[0];
112 : 0 : to_next++;
113 : 0 : held++;
114 : : } else {
115 : 0 : rte_node_enqueue_x1(graph, node,
116 : : next0, from[0]);
117 : : }
118 : :
119 [ # # ]: 0 : if (next1 == next_index) {
120 : 0 : to_next[0] = from[1];
121 : 0 : to_next++;
122 : 0 : held++;
123 : : } else {
124 : 0 : rte_node_enqueue_x1(graph, node,
125 : : next1, from[1]);
126 : : }
127 : :
128 [ # # ]: 0 : if (next2 == next_index) {
129 : 0 : to_next[0] = from[2];
130 : 0 : to_next++;
131 : 0 : held++;
132 : : } else {
133 : 0 : rte_node_enqueue_x1(graph, node,
134 : : next2, from[2]);
135 : : }
136 : :
137 [ # # ]: 0 : if (next3 == next_index) {
138 : 0 : to_next[0] = from[3];
139 : 0 : to_next++;
140 : 0 : held++;
141 : : } else {
142 : 0 : rte_node_enqueue_x1(graph, node,
143 : : next3, from[3]);
144 : : }
145 : 0 : from += 4;
146 : : } else {
147 : 0 : last_spec += 4;
148 : : }
149 : : }
150 : :
151 [ # # ]: 0 : while (n_left_from > 0) {
152 : 0 : mbuf0 = pkts[0];
153 : :
154 : 0 : pkts += 1;
155 : 0 : n_left_from -= 1;
156 : :
157 : 0 : next0 = if_tx_feature_nm->next_index[mbuf0->port];
158 [ # # ]: 0 : if (unlikely(next0 != next_index)) {
159 : : /* Copy things successfully speculated till now */
160 [ # # ]: 0 : rte_memcpy(to_next, from,
161 : : last_spec * sizeof(from[0]));
162 : 0 : from += last_spec;
163 : 0 : to_next += last_spec;
164 : 0 : held += last_spec;
165 : : last_spec = 0;
166 : :
167 : 0 : rte_node_enqueue_x1(graph, node,
168 : : next0, from[0]);
169 : 0 : from += 1;
170 : : } else {
171 : 0 : last_spec += 1;
172 : : }
173 : : }
174 : :
175 : : /* !!! Home run !!! */
176 [ # # ]: 0 : if (likely(last_spec == nb_objs)) {
177 : 0 : rte_node_next_stream_move(graph, node, next_index);
178 : 0 : return nb_objs;
179 : : }
180 : 0 : held += last_spec;
181 [ # # ]: 0 : rte_memcpy(to_next, from, last_spec * sizeof(from[0]));
182 : : rte_node_next_stream_put(graph, node, next_index, held);
183 : :
184 : 0 : IF_TX_FEATURE_LAST_NEXT_INDEX(node->ctx) = next0;
185 : :
186 : 0 : return nb_objs;
187 : : }
188 : :
189 : : static struct rte_node_register if_tx_feature_node = {
190 : : .process = if_tx_feature_node_process,
191 : : .init = if_tx_feature_node_init,
192 : : .name = "interface_tx",
193 : : .nb_edges = 1,
194 : : .next_nodes = {
195 : : [0] = "pkt_drop",
196 : : },
197 : : };
198 : :
199 : : struct rte_node_register *
200 : 0 : if_tx_feature_node_get(void)
201 : : {
202 : 0 : return &if_tx_feature_node;
203 : : }
204 : :
205 : 254 : RTE_NODE_REGISTER(if_tx_feature_node);
206 : :
207 : : /* if_tx feature node */
208 : : struct rte_graph_feature_register if_tx_feature = {
209 : : .feature_name = RTE_IP4_OUTPUT_END_FEATURE_NAME,
210 : : .arc_name = RTE_IP4_OUTPUT_FEATURE_ARC_NAME,
211 : : .feature_process_fn = if_tx_feature_node_process,
212 : : .feature_node = &if_tx_feature_node,
213 : : };
|