Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(C) 2020 Marvell International Ltd.
3 : : */
4 : : #include <eal_export.h>
5 : : #include <rte_ethdev.h>
6 : : #include <rte_ether.h>
7 : : #include <rte_graph.h>
8 : : #include <rte_graph_worker.h>
9 : : #include <rte_graph_feature_arc_worker.h>
10 : : #include <rte_ip.h>
11 : : #include <rte_malloc.h>
12 : : #include <rte_vect.h>
13 : :
14 : : #include "rte_node_ip4_api.h"
15 : :
16 : : #include "ip4_rewrite_priv.h"
17 : : #include "node_private.h"
18 : : #include "interface_tx_feature_priv.h"
19 : :
20 : : #ifndef RTE_IP4_OUTPUT_ARC_INDEXES
21 : : #define RTE_IP4_OUTPUT_ARC_INDEXES RTE_MAX_ETHPORTS
22 : : #endif
23 : :
24 : : struct ip4_rewrite_node_ctx {
25 : : /* Dynamic offset to mbuf priv1 */
26 : : int mbuf_priv1_off;
27 : : /* Dynamic offset to feature arc field */
28 : : int arc_dyn_off;
29 : : /* Cached next index */
30 : : uint16_t next_index;
31 : : /* tx interface of last mbuf */
32 : : uint16_t last_tx_if;
33 : : /* Cached feature arc handle */
34 : : rte_graph_feature_arc_t output_feature_arc;
35 : : };
36 : :
37 : : static struct ip4_rewrite_node_main *ip4_rewrite_nm;
38 : : static int port_to_next_index_diff = -1;
39 : :
40 : : #define IP4_REWRITE_NODE_LAST_NEXT(ctx) \
41 : : (((struct ip4_rewrite_node_ctx *)ctx)->next_index)
42 : :
43 : : #define IP4_REWRITE_NODE_PRIV1_OFF(ctx) \
44 : : (((struct ip4_rewrite_node_ctx *)ctx)->mbuf_priv1_off)
45 : :
46 : : #define IP4_REWRITE_NODE_FEAT_OFF(ctx) \
47 : : (((struct ip4_rewrite_node_ctx *)ctx)->arc_dyn_off)
48 : :
49 : : #define IP4_REWRITE_NODE_OUTPUT_FEATURE_ARC(ctx) \
50 : : (((struct ip4_rewrite_node_ctx *)ctx)->output_feature_arc)
51 : :
52 : : #define IP4_REWRITE_NODE_LAST_TX_IF(ctx) \
53 : : (((struct ip4_rewrite_node_ctx *)ctx)->last_tx_if)
54 : :
55 : : static __rte_always_inline void
56 : : check_output_feature_arc_x1(struct rte_graph_feature_arc *arc, uint16_t *tx_if,
57 : : struct rte_mbuf *mbuf0, uint16_t *next0,
58 : : uint16_t *last_next_index,
59 : : rte_graph_feature_data_t *feature_data, const int feat_dyn)
60 : : {
61 : : struct rte_graph_feature_arc_mbuf_dynfields *d0 = NULL;
62 : : uint16_t port0;
63 : :
64 : : /* make sure packets are not being sent to pkt_drop node */
65 : 0 : if (likely(*next0 >= port_to_next_index_diff)) {
66 : :
67 [ # # ]: 0 : port0 = (*next0) - port_to_next_index_diff;
68 : :
69 : : /* get pointer to feature arc mbuf */
70 : : d0 = rte_graph_feature_arc_mbuf_dynfields_get(mbuf0, feat_dyn);
71 : :
72 : : /* Check if last packet's tx port not same as current */
73 [ # # ]: 0 : if (*tx_if != port0) {
74 : : if (rte_graph_feature_data_first_feature_get(arc, port0,
75 : : &d0->feature_data,
76 : : next0)) {
77 : 0 : mbuf0->port = port0;
78 : : *last_next_index = *next0;
79 : : }
80 : : *tx_if = port0;
81 : 0 : *feature_data = d0->feature_data;
82 : : } else {
83 [ # # ]: 0 : if (rte_graph_feature_data_is_valid(*feature_data)) {
84 : : *next0 = *last_next_index;
85 : 0 : mbuf0->port = port0;
86 : 0 : d0->feature_data = *feature_data;
87 : : }
88 : : }
89 : : }
90 : : }
91 : :
92 : : static __rte_always_inline void
93 : : check_output_feature_arc_x4(struct rte_graph_feature_arc *arc, uint16_t *tx_if,
94 : : struct rte_mbuf *mbuf0, struct rte_mbuf *mbuf1,
95 : : struct rte_mbuf *mbuf2, struct rte_mbuf *mbuf3,
96 : : uint16_t *next0, uint16_t *next1, uint16_t *next2,
97 : : uint16_t *next3, uint16_t *last_next_index,
98 : : rte_graph_feature_data_t *feature_data, const int feat_dyn)
99 : : {
100 : : struct rte_graph_feature_arc_mbuf_dynfields *d0 = NULL, *d1 = NULL, *d2 = NULL, *d3 = NULL;
101 : : uint16_t port0, port1, port2, port3;
102 : : uint16_t xor = 0;
103 : :
104 : : /* get pointer to feature arc dyn field */
105 : : d0 = rte_graph_feature_arc_mbuf_dynfields_get(mbuf0, feat_dyn);
106 : : d1 = rte_graph_feature_arc_mbuf_dynfields_get(mbuf1, feat_dyn);
107 : : d2 = rte_graph_feature_arc_mbuf_dynfields_get(mbuf2, feat_dyn);
108 : : d3 = rte_graph_feature_arc_mbuf_dynfields_get(mbuf3, feat_dyn);
109 : :
110 : : /*
111 : : * Check if all four packets are going to same next_index/port
112 : : */
113 : 0 : xor = (*tx_if + port_to_next_index_diff) ^ (*next0);
114 : 0 : xor += (*next0) ^ (*next1);
115 : 0 : xor += (*next1) ^ (*next2);
116 : 0 : xor += (*next2) ^ (*next3);
117 : :
118 [ # # ]: 0 : if (xor) {
119 : : /* packets tx ports are not same, check first feature for each mbuf
120 : : * make sure next0 != 0 which is pkt_drop
121 : : */
122 : 0 : port0 = (*next0) - port_to_next_index_diff;
123 : 0 : port1 = (*next1) - port_to_next_index_diff;
124 : 0 : port2 = (*next2) - port_to_next_index_diff;
125 : 0 : port3 = (*next3) - port_to_next_index_diff;
126 [ # # # # ]: 0 : if (unlikely((*next0 >= port_to_next_index_diff) &&
127 : : rte_graph_feature_data_first_feature_get(arc, port0,
128 : : &d0->feature_data,
129 : : next0))) {
130 : : /* update next0 from feature arc */
131 : 0 : mbuf0->port = port0;
132 : : }
133 : :
134 [ # # # # ]: 0 : if (unlikely((*next1 >= port_to_next_index_diff) &&
135 : : rte_graph_feature_data_first_feature_get(arc, port1,
136 : : &d1->feature_data,
137 : : next1))) {
138 : 0 : mbuf1->port = port1;
139 : : }
140 : :
141 [ # # # # ]: 0 : if (unlikely((*next2 >= port_to_next_index_diff) &&
142 : : rte_graph_feature_data_first_feature_get(arc, port2,
143 : : &d2->feature_data,
144 : : next2))) {
145 : 0 : mbuf2->port = port2;
146 : : }
147 : :
148 [ # # # # ]: 0 : if (unlikely((*next3 >= port_to_next_index_diff) &&
149 : : rte_graph_feature_data_first_feature_get(arc, port3,
150 : : &d3->feature_data,
151 : : next3))) {
152 : 0 : mbuf3->port = port3;
153 : :
154 : : *tx_if = port3;
155 : : *last_next_index = *next3;
156 : : }
157 : 0 : *feature_data = d3->feature_data;
158 : : } else {
159 : : /* All packets are same as last tx port. Check if feature enabled
160 : : * on last packet is valid or not. If invalid no need to
161 : : * change any next[0-3]
162 : : * Also check packet is not being sent to pkt_drop node
163 : : */
164 [ # # # # ]: 0 : if (unlikely(rte_graph_feature_data_is_valid(*feature_data) &&
165 : : (*next0 != 0))) {
166 : : *next0 = *last_next_index;
167 : : *next1 = *last_next_index;
168 : : *next2 = *last_next_index;
169 : : *next3 = *last_next_index;
170 : :
171 : 0 : d0->feature_data = *feature_data;
172 : 0 : d1->feature_data = *feature_data;
173 : 0 : d2->feature_data = *feature_data;
174 : 0 : d3->feature_data = *feature_data;
175 : :
176 : 0 : mbuf0->port = *tx_if;
177 : 0 : mbuf1->port = *tx_if;
178 : 0 : mbuf2->port = *tx_if;
179 : 0 : mbuf3->port = *tx_if;
180 : : }
181 : : }
182 : : }
183 : :
184 : : static __rte_always_inline uint16_t
185 : : __ip4_rewrite_node_process(struct rte_graph *graph, struct rte_node *node,
186 : : void **objs, uint16_t nb_objs,
187 : : const int dyn, const int feat_dyn, const int check_enabled_features,
188 : : struct rte_graph_feature_arc *out_feature_arc)
189 : : {
190 : : rte_graph_feature_data_t feature_data = RTE_GRAPH_FEATURE_DATA_INVALID;
191 : : struct rte_mbuf *mbuf0, *mbuf1, *mbuf2, *mbuf3, **pkts;
192 : 0 : struct ip4_rewrite_nh_header *nh = ip4_rewrite_nm->nh;
193 : : uint16_t next0, next1, next2, next3, next_index;
194 : : struct rte_ipv4_hdr *ip0, *ip1, *ip2, *ip3;
195 : : uint16_t n_left_from, held = 0, last_spec = 0;
196 : : uint16_t last_tx_if, last_next_index;
197 : : void *d0, *d1, *d2, *d3;
198 : : void **to_next, **from;
199 : : rte_xmm_t priv01;
200 : : rte_xmm_t priv23;
201 : : int i;
202 : :
203 : : /* Speculative next as last next */
204 : 0 : next_index = IP4_REWRITE_NODE_LAST_NEXT(node->ctx);
205 : 0 : rte_prefetch0(nh);
206 : :
207 : : pkts = (struct rte_mbuf **)objs;
208 : : from = objs;
209 : : n_left_from = nb_objs;
210 : :
211 [ # # # # : 0 : for (i = 0; i < 4 && i < n_left_from; i++)
# # # # #
# # # ]
212 : 0 : rte_prefetch0(pkts[i]);
213 : :
214 : : if (check_enabled_features) {
215 : : rte_graph_feature_arc_prefetch(out_feature_arc);
216 : :
217 [ # # ]: 0 : last_tx_if = IP4_REWRITE_NODE_LAST_TX_IF(node->ctx);
218 : :
219 : : /* If feature is enabled on last_tx_if, prefetch data
220 : : * corresponding to first feature
221 : : */
222 [ # # ]: 0 : if (unlikely(rte_graph_feature_data_first_feature_get(out_feature_arc,
223 : : last_tx_if,
224 : : &feature_data,
225 : : &last_next_index)))
226 : : rte_graph_feature_arc_feature_data_prefetch(out_feature_arc,
227 : : feature_data);
228 : :
229 : : /* Reset last_tx_if and last_next_index to call feature arc APIs
230 : : * for initial packets in every node loop
231 : : */
232 : : last_tx_if = UINT16_MAX;
233 : : last_next_index = UINT16_MAX;
234 : : }
235 : :
236 : : /* Get stream for the speculated next node */
237 : 0 : to_next = rte_node_next_stream_get(graph, node, next_index, nb_objs);
238 : : /* Update Ethernet header of pkts */
239 [ # # # # : 0 : while (n_left_from >= 4) {
# # ]
240 [ # # # # : 0 : if (likely(n_left_from > 7)) {
# # ]
241 : : /* Prefetch only next-mbuf struct and priv area.
242 : : * Data need not be prefetched as we only write.
243 : : */
244 : 0 : rte_prefetch0(pkts[4]);
245 : 0 : rte_prefetch0(pkts[5]);
246 : 0 : rte_prefetch0(pkts[6]);
247 : 0 : rte_prefetch0(pkts[7]);
248 : : }
249 : :
250 : 0 : mbuf0 = pkts[0];
251 : 0 : mbuf1 = pkts[1];
252 : 0 : mbuf2 = pkts[2];
253 : 0 : mbuf3 = pkts[3];
254 : :
255 : 0 : pkts += 4;
256 [ # # # # : 0 : n_left_from -= 4;
# # ]
257 : :
258 : 0 : priv01.u64[0] = node_mbuf_priv1(mbuf0, dyn)->u;
259 : 0 : priv01.u64[1] = node_mbuf_priv1(mbuf1, dyn)->u;
260 : 0 : priv23.u64[0] = node_mbuf_priv1(mbuf2, dyn)->u;
261 : 0 : priv23.u64[1] = node_mbuf_priv1(mbuf3, dyn)->u;
262 : :
263 : : /* Increment checksum by one. */
264 : 0 : priv01.u32[1] += rte_cpu_to_be_16(0x0100);
265 : 0 : priv01.u32[3] += rte_cpu_to_be_16(0x0100);
266 : 0 : priv23.u32[1] += rte_cpu_to_be_16(0x0100);
267 : 0 : priv23.u32[3] += rte_cpu_to_be_16(0x0100);
268 : :
269 : : /* Update ttl,cksum rewrite ethernet hdr on mbuf0 */
270 : 0 : d0 = rte_pktmbuf_mtod(mbuf0, void *);
271 : 0 : rte_memcpy(d0, nh[priv01.u16[0]].rewrite_data,
272 [ # # # # : 0 : nh[priv01.u16[0]].rewrite_len);
# # ]
273 : :
274 : 0 : next0 = nh[priv01.u16[0]].tx_node;
275 : : ip0 = (struct rte_ipv4_hdr *)((uint8_t *)d0 +
276 : : sizeof(struct rte_ether_hdr));
277 : 0 : ip0->time_to_live = priv01.u16[1] - 1;
278 : 0 : ip0->hdr_checksum = priv01.u16[2] + priv01.u16[3];
279 : :
280 : : /* Update ttl,cksum rewrite ethernet hdr on mbuf1 */
281 : 0 : d1 = rte_pktmbuf_mtod(mbuf1, void *);
282 : 0 : rte_memcpy(d1, nh[priv01.u16[4]].rewrite_data,
283 [ # # # # : 0 : nh[priv01.u16[4]].rewrite_len);
# # ]
284 : :
285 : 0 : next1 = nh[priv01.u16[4]].tx_node;
286 : : ip1 = (struct rte_ipv4_hdr *)((uint8_t *)d1 +
287 : : sizeof(struct rte_ether_hdr));
288 : 0 : ip1->time_to_live = priv01.u16[5] - 1;
289 : 0 : ip1->hdr_checksum = priv01.u16[6] + priv01.u16[7];
290 : :
291 : : /* Update ttl,cksum rewrite ethernet hdr on mbuf2 */
292 : 0 : d2 = rte_pktmbuf_mtod(mbuf2, void *);
293 : 0 : rte_memcpy(d2, nh[priv23.u16[0]].rewrite_data,
294 [ # # # # : 0 : nh[priv23.u16[0]].rewrite_len);
# # ]
295 : 0 : next2 = nh[priv23.u16[0]].tx_node;
296 : : ip2 = (struct rte_ipv4_hdr *)((uint8_t *)d2 +
297 : : sizeof(struct rte_ether_hdr));
298 : 0 : ip2->time_to_live = priv23.u16[1] - 1;
299 : 0 : ip2->hdr_checksum = priv23.u16[2] + priv23.u16[3];
300 : :
301 : : /* Update ttl,cksum rewrite ethernet hdr on mbuf3 */
302 : 0 : d3 = rte_pktmbuf_mtod(mbuf3, void *);
303 : 0 : rte_memcpy(d3, nh[priv23.u16[4]].rewrite_data,
304 [ # # # # : 0 : nh[priv23.u16[4]].rewrite_len);
# # ]
305 : :
306 : 0 : next3 = nh[priv23.u16[4]].tx_node;
307 : : ip3 = (struct rte_ipv4_hdr *)((uint8_t *)d3 +
308 : : sizeof(struct rte_ether_hdr));
309 : 0 : ip3->time_to_live = priv23.u16[5] - 1;
310 [ # # # # ]: 0 : ip3->hdr_checksum = priv23.u16[6] + priv23.u16[7];
311 : :
312 : : /* Once all mbufs are updated with next hop data.
313 : : * check if any feature is enabled to override
314 : : * next edges
315 : : */
316 : : if (check_enabled_features)
317 : : check_output_feature_arc_x4(out_feature_arc, &last_tx_if,
318 : : mbuf0, mbuf1, mbuf2, mbuf3,
319 : : &next0, &next1, &next2, &next3,
320 : : &last_next_index, &feature_data, feat_dyn);
321 : :
322 : : /* Enqueue four to next node */
323 : 0 : rte_edge_t fix_spec =
324 [ # # # # : 0 : ((next_index == next0) && (next0 == next1) &&
# # # # #
# # # ]
325 [ # # # # : 0 : (next1 == next2) && (next2 == next3));
# # # # #
# # # ]
326 : :
327 [ # # # # : 0 : if (unlikely(fix_spec == 0)) {
# # ]
328 : : /* Copy things successfully speculated till now */
329 [ # # # # : 0 : rte_memcpy(to_next, from, last_spec * sizeof(from[0]));
# # ]
330 : 0 : from += last_spec;
331 : 0 : to_next += last_spec;
332 : 0 : held += last_spec;
333 : : last_spec = 0;
334 : :
335 : : /* next0 */
336 [ # # # # : 0 : if (next_index == next0) {
# # ]
337 : 0 : to_next[0] = from[0];
338 : 0 : to_next++;
339 : 0 : held++;
340 : : } else {
341 : 0 : rte_node_enqueue_x1(graph, node, next0,
342 : : from[0]);
343 : : }
344 : :
345 : : /* next1 */
346 [ # # # # : 0 : if (next_index == next1) {
# # ]
347 : 0 : to_next[0] = from[1];
348 : 0 : to_next++;
349 : 0 : held++;
350 : : } else {
351 : 0 : rte_node_enqueue_x1(graph, node, next1,
352 : : from[1]);
353 : : }
354 : :
355 : : /* next2 */
356 [ # # # # : 0 : if (next_index == next2) {
# # ]
357 : 0 : to_next[0] = from[2];
358 : 0 : to_next++;
359 : 0 : held++;
360 : : } else {
361 : 0 : rte_node_enqueue_x1(graph, node, next2,
362 : : from[2]);
363 : : }
364 : :
365 : : /* next3 */
366 [ # # # # : 0 : if (next_index == next3) {
# # ]
367 : 0 : to_next[0] = from[3];
368 : 0 : to_next++;
369 : 0 : held++;
370 : : } else {
371 : 0 : rte_node_enqueue_x1(graph, node, next3,
372 : : from[3]);
373 : : }
374 : :
375 : 0 : from += 4;
376 : :
377 : : /* Change speculation if last two are same */
378 [ # # # # : 0 : if ((next_index != next3) && (next2 == next3)) {
# # # # #
# # # ]
379 : : /* Put the current speculated node */
380 : 0 : rte_node_next_stream_put(graph, node,
381 : : next_index, held);
382 : : held = 0;
383 : :
384 : : /* Get next speculated stream */
385 : : next_index = next3;
386 : 0 : to_next = rte_node_next_stream_get(
387 : : graph, node, next_index, nb_objs);
388 : : }
389 : : } else {
390 : 0 : last_spec += 4;
391 : : }
392 : : }
393 : :
394 [ # # # # : 0 : while (n_left_from > 0) {
# # ]
395 : : uint16_t chksum;
396 : :
397 : 0 : mbuf0 = pkts[0];
398 : :
399 : 0 : pkts += 1;
400 : 0 : n_left_from -= 1;
401 : :
402 [ # # # # : 0 : d0 = rte_pktmbuf_mtod(mbuf0, void *);
# # ]
403 : 0 : rte_memcpy(d0, nh[node_mbuf_priv1(mbuf0, dyn)->nh].rewrite_data,
404 [ # # # # : 0 : nh[node_mbuf_priv1(mbuf0, dyn)->nh].rewrite_len);
# # ]
405 : :
406 : 0 : next0 = nh[node_mbuf_priv1(mbuf0, dyn)->nh].tx_node;
407 : : ip0 = (struct rte_ipv4_hdr *)((uint8_t *)d0 +
408 : : sizeof(struct rte_ether_hdr));
409 : 0 : chksum = node_mbuf_priv1(mbuf0, dyn)->cksum +
410 : 0 : rte_cpu_to_be_16(0x0100);
411 : 0 : chksum += chksum >= 0xffff;
412 : 0 : ip0->hdr_checksum = chksum;
413 [ # # ]: 0 : ip0->time_to_live = node_mbuf_priv1(mbuf0, dyn)->ttl - 1;
414 : :
415 : : if (check_enabled_features)
416 : : check_output_feature_arc_x1(out_feature_arc, &last_tx_if,
417 : : mbuf0, &next0, &last_next_index,
418 : : &feature_data, feat_dyn);
419 : :
420 [ # # # # : 0 : if (unlikely(next_index ^ next0)) {
# # ]
421 : : /* Copy things successfully speculated till now */
422 [ # # # # : 0 : rte_memcpy(to_next, from, last_spec * sizeof(from[0]));
# # ]
423 : 0 : from += last_spec;
424 : 0 : to_next += last_spec;
425 : 0 : held += last_spec;
426 : : last_spec = 0;
427 : :
428 : 0 : rte_node_enqueue_x1(graph, node, next0, from[0]);
429 : 0 : from += 1;
430 : : } else {
431 : 0 : last_spec += 1;
432 : : }
433 : : }
434 : :
435 : : /* !!! Home run !!! */
436 [ # # # # : 0 : if (likely(last_spec == nb_objs)) {
# # ]
437 : 0 : rte_node_next_stream_move(graph, node, next_index);
438 : 0 : return nb_objs;
439 : : }
440 : :
441 : 0 : held += last_spec;
442 [ # # # # : 0 : rte_memcpy(to_next, from, last_spec * sizeof(from[0]));
# # ]
443 : 0 : rte_node_next_stream_put(graph, node, next_index, held);
444 : : /* Save the last next used */
445 : 0 : IP4_REWRITE_NODE_LAST_NEXT(node->ctx) = next_index;
446 : :
447 : : if (check_enabled_features)
448 : 0 : IP4_REWRITE_NODE_LAST_TX_IF(node->ctx) = last_tx_if;
449 : :
450 : : return nb_objs;
451 : : }
452 : :
453 : : static uint16_t
454 : 0 : ip4_rewrite_feature_node_process(struct rte_graph *graph, struct rte_node *node,
455 : : void **objs, uint16_t nb_objs)
456 : : {
457 : 0 : const int dyn = IP4_REWRITE_NODE_PRIV1_OFF(node->ctx);
458 : 0 : const int feat_dyn = IP4_REWRITE_NODE_FEAT_OFF(node->ctx);
459 : : struct rte_graph_feature_arc *arc = NULL;
460 : :
461 [ # # ]: 0 : arc = rte_graph_feature_arc_get(IP4_REWRITE_NODE_OUTPUT_FEATURE_ARC(node->ctx));
462 [ # # # # ]: 0 : if (unlikely(rte_graph_feature_arc_is_any_feature_enabled(arc) &&
463 : : (port_to_next_index_diff > 0)))
464 : 0 : return __ip4_rewrite_node_process(graph, node, objs, nb_objs, dyn, feat_dyn,
465 : : 1 /* check features */, arc);
466 : :
467 : 0 : return __ip4_rewrite_node_process(graph, node, objs, nb_objs, dyn, 0,
468 : : 0/* don't check features*/,
469 : : arc /* don't care*/);
470 : : }
471 : :
472 : : static uint16_t
473 : 0 : ip4_rewrite_node_process(struct rte_graph *graph, struct rte_node *node,
474 : : void **objs, uint16_t nb_objs)
475 : : {
476 : 0 : const int dyn = IP4_REWRITE_NODE_PRIV1_OFF(node->ctx);
477 : :
478 : 0 : return __ip4_rewrite_node_process(graph, node, objs, nb_objs, dyn, 0,
479 : : 0/* don't check features*/,
480 : : NULL/* don't care */);
481 : : }
482 : :
483 : :
484 : : static int
485 : 0 : ip4_rewrite_node_init(const struct rte_graph *graph, struct rte_node *node)
486 : : {
487 : 0 : rte_graph_feature_arc_t feature_arc = RTE_GRAPH_FEATURE_ARC_INITIALIZER;
488 : : static bool init_once;
489 : : int dyn;
490 : :
491 : : RTE_SET_USED(graph);
492 : : RTE_BUILD_BUG_ON(sizeof(struct ip4_rewrite_node_ctx) > RTE_NODE_CTX_SZ);
493 : :
494 : 0 : dyn = rte_node_mbuf_dynfield_register();
495 [ # # ]: 0 : if (dyn < 0) {
496 : 0 : node_err("ip4_rewrite", "Failed to register mbuf dynfield");
497 : 0 : return -rte_errno;
498 : : }
499 : :
500 [ # # ]: 0 : if (!init_once) {
501 : : /* Create ipv4-output feature arc, if not created
502 : : */
503 [ # # ]: 0 : if (rte_graph_feature_arc_lookup_by_name(RTE_IP4_OUTPUT_FEATURE_ARC_NAME,
504 : : &feature_arc) < 0) {
505 : 0 : node_err("ip4_rewrite", "Feature arc \"%s\" not found",
506 : : RTE_IP4_OUTPUT_FEATURE_ARC_NAME);
507 : : } else {
508 : 0 : node_err("ip4_rewrite", "Feature arc \"%s\" found",
509 : : RTE_IP4_OUTPUT_FEATURE_ARC_NAME);
510 : : }
511 : :
512 : 0 : IP4_REWRITE_NODE_OUTPUT_FEATURE_ARC(node->ctx) = feature_arc;
513 : :
514 [ # # # # ]: 0 : if (rte_graph_feature_arc_get(feature_arc))
515 : 0 : IP4_REWRITE_NODE_FEAT_OFF(node->ctx) =
516 : 0 : rte_graph_feature_arc_get(feature_arc)->mbuf_dyn_offset;
517 : :
518 : : /* By default, set cached next node to pkt_drop */
519 : 0 : IP4_REWRITE_NODE_LAST_NEXT(node->ctx) = 0;
520 : 0 : IP4_REWRITE_NODE_LAST_TX_IF(node->ctx) = 0;
521 : :
522 : 0 : init_once = true;
523 : : }
524 : 0 : IP4_REWRITE_NODE_PRIV1_OFF(node->ctx) = dyn;
525 : 0 : node_dbg("ip4_rewrite", "Initialized ip4_rewrite node initialized");
526 : :
527 : 0 : return 0;
528 : : }
529 : :
530 : : int
531 : 0 : ip4_rewrite_set_next(uint16_t port_id, uint16_t next_index)
532 : : {
533 : : static int once;
534 : :
535 [ # # ]: 0 : if (ip4_rewrite_nm == NULL) {
536 : 0 : ip4_rewrite_nm = rte_zmalloc(
537 : : "ip4_rewrite", sizeof(struct ip4_rewrite_node_main),
538 : : RTE_CACHE_LINE_SIZE);
539 [ # # ]: 0 : if (ip4_rewrite_nm == NULL)
540 : : return -ENOMEM;
541 : : }
542 [ # # ]: 0 : if (!once) {
543 : 0 : port_to_next_index_diff = next_index - port_id;
544 : 0 : once = 1;
545 : : }
546 : 0 : ip4_rewrite_nm->next_index[port_id] = next_index;
547 : :
548 : 0 : return 0;
549 : : }
550 : :
551 : : RTE_EXPORT_SYMBOL(rte_node_ip4_rewrite_add)
552 : : int
553 : 0 : rte_node_ip4_rewrite_add(uint16_t next_hop, uint8_t *rewrite_data,
554 : : uint8_t rewrite_len, uint16_t dst_port)
555 : : {
556 : : struct ip4_rewrite_nh_header *nh;
557 : :
558 [ # # ]: 0 : if (next_hop >= RTE_GRAPH_IP4_REWRITE_MAX_NH)
559 : : return -EINVAL;
560 : :
561 [ # # ]: 0 : if (rewrite_len > RTE_GRAPH_IP4_REWRITE_MAX_LEN)
562 : : return -EINVAL;
563 : :
564 [ # # ]: 0 : if (ip4_rewrite_nm == NULL) {
565 : 0 : ip4_rewrite_nm = rte_zmalloc(
566 : : "ip4_rewrite", sizeof(struct ip4_rewrite_node_main),
567 : : RTE_CACHE_LINE_SIZE);
568 [ # # ]: 0 : if (ip4_rewrite_nm == NULL)
569 : : return -ENOMEM;
570 : : }
571 : :
572 : : /* Check if dst port doesn't exist as edge */
573 [ # # ]: 0 : if (!ip4_rewrite_nm->next_index[dst_port])
574 : : return -EINVAL;
575 : :
576 : : /* Update next hop */
577 : 0 : nh = &ip4_rewrite_nm->nh[next_hop];
578 : :
579 : 0 : memcpy(nh->rewrite_data, rewrite_data, rewrite_len);
580 : 0 : nh->tx_node = ip4_rewrite_nm->next_index[dst_port];
581 : 0 : nh->rewrite_len = rewrite_len;
582 : 0 : nh->enabled = true;
583 : :
584 : 0 : return 0;
585 : : }
586 : :
587 : : static struct rte_node_register ip4_rewrite_node = {
588 : : .process = ip4_rewrite_node_process,
589 : : .name = "ip4_rewrite",
590 : : /* Default edge i.e '0' is pkt drop */
591 : : .nb_edges = 1,
592 : : .next_nodes = {
593 : : [0] = "pkt_drop",
594 : : },
595 : : .init = ip4_rewrite_node_init,
596 : : };
597 : :
598 : : struct rte_node_register *
599 : 0 : ip4_rewrite_node_get(void)
600 : : {
601 : 0 : return &ip4_rewrite_node;
602 : : }
603 : :
604 : 254 : RTE_NODE_REGISTER(ip4_rewrite_node);
605 : :
606 : : /* IP4 output arc */
607 : : static struct rte_graph_feature_arc_register ip4_output_arc = {
608 : : .arc_name = RTE_IP4_OUTPUT_FEATURE_ARC_NAME,
609 : :
610 : : /* This arc works on all ethdevs */
611 : : .max_indexes = RTE_IP4_OUTPUT_ARC_INDEXES,
612 : :
613 : : .start_node = &ip4_rewrite_node,
614 : :
615 : : /* overwrites start_node->process() function with following only if
616 : : * application calls rte_graph_feature_arc_init()
617 : : */
618 : : .start_node_feature_process_fn = ip4_rewrite_feature_node_process,
619 : :
620 : : /* end feature node of an arc*/
621 : : .end_feature = &if_tx_feature,
622 : : };
623 : :
624 : 254 : RTE_GRAPH_FEATURE_ARC_REGISTER(ip4_output_arc);
|