DPDK 25.07.0-rc1
rte_graph_worker_common.h
Go to the documentation of this file.
1/* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(C) 2020 Marvell International Ltd.
3 */
4
5#ifndef _RTE_GRAPH_WORKER_COMMON_H_
6#define _RTE_GRAPH_WORKER_COMMON_H_
7
15#include <assert.h>
16#include <stdalign.h>
17#include <stddef.h>
18
19#include <rte_common.h>
20#include <rte_cycles.h>
21#include <rte_prefetch.h>
22#include <rte_memcpy.h>
23#include <rte_memory.h>
24
25#include "rte_graph.h"
26
27#ifdef __cplusplus
28extern "C" {
29#endif
30
32/* When adding a new graph model entry, update rte_graph_model_is_valid() implementation. */
33#define RTE_GRAPH_MODEL_RTC 0
34#define RTE_GRAPH_MODEL_MCORE_DISPATCH 1
36#define RTE_GRAPH_MODEL_DEFAULT RTE_GRAPH_MODEL_RTC
43SLIST_HEAD(rte_graph_rq_head, rte_graph);
44
50struct __rte_cache_aligned rte_graph {
51 /* Fast path area. */
52 uint32_t tail;
53 uint32_t head;
54 uint32_t cir_mask;
55 rte_node_t nb_nodes;
56 rte_graph_off_t *cir_start;
57 rte_graph_off_t nodes_start;
58 uint8_t model;
59 uint8_t reserved1;
60 uint16_t reserved2;
61 union {
62 /* Fast schedule area for mcore dispatch model */
63 struct {
64 alignas(RTE_CACHE_LINE_SIZE) struct rte_graph_rq_head *rq;
65 /* The run-queue */
66 struct rte_graph_rq_head rq_head; /* The head for run-queue list */
67
68 unsigned int lcore_id;
69 struct rte_ring *wq;
70 struct rte_mempool *mp;
71 } dispatch;
72 };
73 SLIST_ENTRY(rte_graph) next; /* The next for rte_graph list */
74 /* End of Fast path area.*/
75 rte_graph_t id;
76 int socket;
78 bool pcap_enable;
80 uint64_t nb_pkt_captured;
82 uint64_t nb_pkt_to_capture;
83 char pcap_filename[RTE_GRAPH_PCAP_FILE_SZ];
84 uint64_t fence;
85};
86
92struct __rte_cache_aligned rte_node {
93 /* Slow path area */
94 uint64_t fence;
95 rte_graph_off_t next;
96 rte_node_t id;
97 rte_node_t parent_id;
98 rte_edge_t nb_edges;
99 uint32_t realloc_count;
101 char parent[RTE_NODE_NAMESIZE];
102 char name[RTE_NODE_NAMESIZE];
105 rte_node_process_t original_process;
106
108 union {
109 alignas(RTE_CACHE_LINE_MIN_SIZE) struct {
110 unsigned int lcore_id;
111 uint64_t total_sched_objs;
112 uint64_t total_sched_fail;
113 struct rte_graph *graph;
114 } dispatch;
115 };
116
119 rte_graph_off_t xstat_off;
122 __extension__ struct __rte_cache_aligned {
123#define RTE_NODE_CTX_SZ 16
124 union {
125 uint8_t ctx[RTE_NODE_CTX_SZ];
126 __extension__ struct {
127 void *ctx_ptr;
128 void *ctx_ptr2;
129 };
130 };
131 uint16_t size;
132 uint16_t idx;
134 uint64_t total_cycles;
135 uint64_t total_calls;
136 uint64_t total_objs;
137 union {
138 void **objs;
139 uint64_t objs_u64;
140 };
141 union {
143 uint64_t process_u64;
144 };
145 alignas(RTE_CACHE_LINE_MIN_SIZE) struct rte_node *nodes[];
146 };
147};
148
149static_assert(offsetof(struct rte_node, nodes) - offsetof(struct rte_node, ctx)
150 == RTE_CACHE_LINE_MIN_SIZE, "rte_node fast path area must fit in 64 bytes");
151
164void __rte_node_stream_alloc(struct rte_graph *graph, struct rte_node *node);
165
180void __rte_node_stream_alloc_size(struct rte_graph *graph,
181 struct rte_node *node, uint16_t req_size);
182
183/* Fast path helper functions */
184
195static __rte_always_inline void
196__rte_node_process(struct rte_graph *graph, struct rte_node *node)
197{
198 uint64_t start;
199 uint16_t rc;
200 void **objs;
201
202 RTE_ASSERT(node->fence == RTE_GRAPH_FENCE);
203 objs = node->objs;
204 rte_prefetch0(objs);
205
207 start = rte_rdtsc();
208 rc = node->process(graph, node, objs, node->idx);
209 node->total_cycles += rte_rdtsc() - start;
210 node->total_calls++;
211 node->total_objs += rc;
212 } else {
213 node->process(graph, node, objs, node->idx);
214 }
215 node->idx = 0;
216}
217
228static __rte_always_inline void
229__rte_node_enqueue_tail_update(struct rte_graph *graph, struct rte_node *node)
230{
231 uint32_t tail;
232
233 tail = graph->tail;
234 graph->cir_start[tail++] = node->off;
235 graph->tail = tail & graph->cir_mask;
236}
237
255static __rte_always_inline void
256__rte_node_enqueue_prologue(struct rte_graph *graph, struct rte_node *node,
257 const uint16_t idx, const uint16_t space)
258{
259
260 /* Add to the pending stream list if the node is new */
261 if (idx == 0)
262 __rte_node_enqueue_tail_update(graph, node);
263
264 if (unlikely(node->size < (idx + space)))
265 __rte_node_stream_alloc_size(graph, node, node->size + space);
266}
267
281static __rte_always_inline struct rte_node *
282__rte_node_next_node_get(struct rte_node *node, rte_edge_t next)
283{
284 RTE_ASSERT(next < node->nb_edges);
285 RTE_ASSERT(node->fence == RTE_GRAPH_FENCE);
286 node = node->nodes[next];
287 RTE_ASSERT(node->fence == RTE_GRAPH_FENCE);
288
289 return node;
290}
291
307static inline void
308rte_node_enqueue(struct rte_graph *graph, struct rte_node *node,
309 rte_edge_t next, void **objs, uint16_t nb_objs)
310{
311 node = __rte_node_next_node_get(node, next);
312 const uint16_t idx = node->idx;
313
314 __rte_node_enqueue_prologue(graph, node, idx, nb_objs);
315
316 rte_memcpy(&node->objs[idx], objs, nb_objs * sizeof(void *));
317 node->idx = idx + nb_objs;
318}
319
333static inline void
334rte_node_enqueue_x1(struct rte_graph *graph, struct rte_node *node,
335 rte_edge_t next, void *obj)
336{
337 node = __rte_node_next_node_get(node, next);
338 uint16_t idx = node->idx;
339
340 __rte_node_enqueue_prologue(graph, node, idx, 1);
341
342 node->objs[idx++] = obj;
343 node->idx = idx;
344}
345
362static inline void
363rte_node_enqueue_x2(struct rte_graph *graph, struct rte_node *node,
364 rte_edge_t next, void *obj0, void *obj1)
365{
366 node = __rte_node_next_node_get(node, next);
367 uint16_t idx = node->idx;
368
369 __rte_node_enqueue_prologue(graph, node, idx, 2);
370
371 node->objs[idx++] = obj0;
372 node->objs[idx++] = obj1;
373 node->idx = idx;
374}
375
396static inline void
397rte_node_enqueue_x4(struct rte_graph *graph, struct rte_node *node,
398 rte_edge_t next, void *obj0, void *obj1, void *obj2,
399 void *obj3)
400{
401 node = __rte_node_next_node_get(node, next);
402 uint16_t idx = node->idx;
403
404 __rte_node_enqueue_prologue(graph, node, idx, 4);
405
406 node->objs[idx++] = obj0;
407 node->objs[idx++] = obj1;
408 node->objs[idx++] = obj2;
409 node->objs[idx++] = obj3;
410 node->idx = idx;
411}
412
429static inline void
430rte_node_enqueue_next(struct rte_graph *graph, struct rte_node *node,
431 rte_edge_t *nexts, void **objs, uint16_t nb_objs)
432{
433 uint16_t i;
434
435 for (i = 0; i < nb_objs; i++)
436 rte_node_enqueue_x1(graph, node, nexts[i], objs[i]);
437}
438
458static inline void **
459rte_node_next_stream_get(struct rte_graph *graph, struct rte_node *node,
460 rte_edge_t next, uint16_t nb_objs)
461{
462 node = __rte_node_next_node_get(node, next);
463 const uint16_t idx = node->idx;
464 uint16_t free_space = node->size - idx;
465
466 if (unlikely(free_space < nb_objs))
467 __rte_node_stream_alloc_size(graph, node, node->size + nb_objs);
468
469 return &node->objs[idx];
470}
471
488static inline void
489rte_node_next_stream_put(struct rte_graph *graph, struct rte_node *node,
490 rte_edge_t next, uint16_t idx)
491{
492 if (unlikely(!idx))
493 return;
494
495 node = __rte_node_next_node_get(node, next);
496 if (node->idx == 0)
497 __rte_node_enqueue_tail_update(graph, node);
498
499 node->idx += idx;
500}
501
516static inline void
517rte_node_next_stream_move(struct rte_graph *graph, struct rte_node *src,
518 rte_edge_t next)
519{
520 struct rte_node *dst = __rte_node_next_node_get(src, next);
521
522 /* Let swap the pointers if dst don't have valid objs */
523 if (likely(dst->idx == 0)) {
524 void **dobjs = dst->objs;
525 uint16_t dsz = dst->size;
526 dst->objs = src->objs;
527 dst->size = src->size;
528 src->objs = dobjs;
529 src->size = dsz;
530 dst->idx = src->idx;
531 __rte_node_enqueue_tail_update(graph, dst);
532 } else { /* Move the objects from src node to dst node */
533 rte_node_enqueue(graph, src, next, src->objs, src->idx);
534 }
535}
536
546bool
548
559int rte_graph_worker_model_set(uint8_t model);
560
573uint8_t rte_graph_worker_model_get(struct rte_graph *graph);
574
588uint8_t rte_graph_worker_model_no_check_get(struct rte_graph *graph)
589{
590 return graph->model;
591}
592
605__rte_experimental
606static inline void
607rte_node_xstat_increment(struct rte_node *node, uint16_t xstat_id, uint64_t value)
608{
610 uint64_t *xstat = (uint64_t *)RTE_PTR_ADD(node, node->xstat_off);
611 xstat[xstat_id] += value;
612 }
613}
614
615#ifdef __cplusplus
616}
617#endif
618
619#endif /* _RTE_GRAPH_WORKER_COIMMON_H_ */
#define likely(x)
#define unlikely(x)
#define RTE_CACHE_LINE_MIN_SIZE
Definition: rte_common.h:736
#define offsetof(TYPE, MEMBER)
Definition: rte_common.h:836
#define RTE_PTR_ADD(ptr, x)
Definition: rte_common.h:554
#define __rte_cache_aligned
Definition: rte_common.h:739
#define __rte_always_inline
Definition: rte_common.h:490
uint16_t(* rte_node_process_t)(struct rte_graph *graph, struct rte_node *node, void **objs, uint16_t nb_objs)
Definition: rte_graph.h:95
uint32_t rte_node_t
Definition: rte_graph.h:42
#define RTE_GRAPH_FENCE
Definition: rte_graph.h:39
uint16_t rte_edge_t
Definition: rte_graph.h:43
#define RTE_NODE_NAMESIZE
Definition: rte_graph.h:32
#define RTE_GRAPH_PCAP_FILE_SZ
Definition: rte_graph.h:34
uint32_t rte_graph_off_t
Definition: rte_graph.h:41
uint16_t rte_graph_t
Definition: rte_graph.h:44
#define RTE_GRAPH_NAMESIZE
Definition: rte_graph.h:31
static __rte_always_inline int rte_graph_has_stats_feature(void)
Definition: rte_graph.h:716
static __rte_always_inline uint8_t rte_graph_worker_model_no_check_get(struct rte_graph *graph)
static void rte_node_enqueue_x4(struct rte_graph *graph, struct rte_node *node, rte_edge_t next, void *obj0, void *obj1, void *obj2, void *obj3)
bool rte_graph_model_is_valid(uint8_t model)
static void rte_node_next_stream_put(struct rte_graph *graph, struct rte_node *node, rte_edge_t next, uint16_t idx)
static void rte_node_enqueue(struct rte_graph *graph, struct rte_node *node, rte_edge_t next, void **objs, uint16_t nb_objs)
static void rte_node_next_stream_move(struct rte_graph *graph, struct rte_node *src, rte_edge_t next)
int rte_graph_worker_model_set(uint8_t model)
static void rte_node_enqueue_next(struct rte_graph *graph, struct rte_node *node, rte_edge_t *nexts, void **objs, uint16_t nb_objs)
static void rte_node_enqueue_x1(struct rte_graph *graph, struct rte_node *node, rte_edge_t next, void *obj)
static __rte_experimental void rte_node_xstat_increment(struct rte_node *node, uint16_t xstat_id, uint64_t value)
static void ** rte_node_next_stream_get(struct rte_graph *graph, struct rte_node *node, rte_edge_t next, uint16_t nb_objs)
static void rte_node_enqueue_x2(struct rte_graph *graph, struct rte_node *node, rte_edge_t next, void *obj0, void *obj1)
uint8_t rte_graph_worker_model_get(struct rte_graph *graph)
static void * rte_memcpy(void *dst, const void *src, size_t n)
static void rte_prefetch0(const volatile void *p)
char name[RTE_MEMPOOL_NAMESIZE]
Definition: rte_mempool.h:231