DPDK 25.11.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 packets_enqueued_cb notify_cb;
72 uint64_t cb_priv;
73 } dispatch;
74 };
75 SLIST_ENTRY(rte_graph) next; /* The next for rte_graph list */
76 /* End of Fast path area.*/
77 rte_graph_t id;
78 int socket;
80 bool pcap_enable;
82 uint64_t nb_pkt_captured;
84 uint64_t nb_pkt_to_capture;
85 char pcap_filename[RTE_GRAPH_PCAP_FILE_SZ];
86 uint64_t fence;
87};
88
94struct __rte_cache_aligned rte_node {
95 /* Slow path area */
96 uint64_t fence;
97 rte_graph_off_t next;
98 rte_node_t id;
99 rte_node_t parent_id;
100 rte_edge_t nb_edges;
101 uint32_t realloc_count;
103 char parent[RTE_NODE_NAMESIZE];
104 char name[RTE_NODE_NAMESIZE];
107 rte_node_process_t original_process;
108
110 union {
111 alignas(RTE_CACHE_LINE_MIN_SIZE) struct {
112 unsigned int lcore_id;
113 uint64_t total_sched_objs;
114 uint64_t total_sched_fail;
115 struct rte_graph *graph;
116 } dispatch;
117 };
118
121 rte_graph_off_t xstat_off;
124 __extension__ struct __rte_cache_aligned {
125#define RTE_NODE_CTX_SZ 16
126 union {
127 uint8_t ctx[RTE_NODE_CTX_SZ];
128 __extension__ struct {
129 void *ctx_ptr;
130 void *ctx_ptr2;
131 };
132 };
133 uint16_t size;
134 uint16_t idx;
136 uint64_t total_cycles;
137 uint64_t total_calls;
138 uint64_t total_objs;
139 union {
140 void **objs;
141 uint64_t objs_u64;
142 };
143 union {
145 uint64_t process_u64;
146 };
147 alignas(RTE_CACHE_LINE_MIN_SIZE) struct rte_node *nodes[];
148 };
149};
150
151static_assert(offsetof(struct rte_node, nodes) - offsetof(struct rte_node, ctx)
152 == RTE_CACHE_LINE_MIN_SIZE, "rte_node fast path area must fit in 64 bytes");
153
166void __rte_node_stream_alloc(struct rte_graph *graph, struct rte_node *node);
167
182void __rte_node_stream_alloc_size(struct rte_graph *graph,
183 struct rte_node *node, uint16_t req_size);
184
185/* Fast path helper functions */
186
197static __rte_always_inline void
198__rte_node_process(struct rte_graph *graph, struct rte_node *node)
199{
200 uint64_t start;
201 uint16_t rc;
202 void **objs;
203
204 RTE_ASSERT(node->fence == RTE_GRAPH_FENCE);
205 objs = node->objs;
206 rte_prefetch0(objs);
207
209 start = rte_rdtsc();
210 rc = node->process(graph, node, objs, node->idx);
211 node->total_cycles += rte_rdtsc() - start;
212 node->total_calls++;
213 node->total_objs += rc;
214 } else {
215 node->process(graph, node, objs, node->idx);
216 }
217 node->idx = 0;
218}
219
230static __rte_always_inline void
231__rte_node_enqueue_tail_update(struct rte_graph *graph, struct rte_node *node)
232{
233 uint32_t tail;
234
235 tail = graph->tail;
236 graph->cir_start[tail++] = node->off;
237 graph->tail = tail & graph->cir_mask;
238}
239
257static __rte_always_inline void
258__rte_node_enqueue_prologue(struct rte_graph *graph, struct rte_node *node,
259 const uint16_t idx, const uint16_t space)
260{
261
262 /* Add to the pending stream list if the node is new */
263 if (idx == 0)
264 __rte_node_enqueue_tail_update(graph, node);
265
266 if (unlikely(node->size < (idx + space)))
267 __rte_node_stream_alloc_size(graph, node, node->size + space);
268}
269
283static __rte_always_inline struct rte_node *
284__rte_node_next_node_get(struct rte_node *node, rte_edge_t next)
285{
286 RTE_ASSERT(next < node->nb_edges);
287 RTE_ASSERT(node->fence == RTE_GRAPH_FENCE);
288 node = node->nodes[next];
289 RTE_ASSERT(node->fence == RTE_GRAPH_FENCE);
290
291 return node;
292}
293
309static inline void
310rte_node_enqueue(struct rte_graph *graph, struct rte_node *node,
311 rte_edge_t next, void **objs, uint16_t nb_objs)
312{
313 node = __rte_node_next_node_get(node, next);
314 const uint16_t idx = node->idx;
315
316 __rte_node_enqueue_prologue(graph, node, idx, nb_objs);
317
318 rte_memcpy(&node->objs[idx], objs, nb_objs * sizeof(void *));
319 node->idx = idx + nb_objs;
320}
321
335static inline void
336rte_node_enqueue_x1(struct rte_graph *graph, struct rte_node *node,
337 rte_edge_t next, void *obj)
338{
339 node = __rte_node_next_node_get(node, next);
340 uint16_t idx = node->idx;
341
342 __rte_node_enqueue_prologue(graph, node, idx, 1);
343
344 node->objs[idx++] = obj;
345 node->idx = idx;
346}
347
364static inline void
365rte_node_enqueue_x2(struct rte_graph *graph, struct rte_node *node,
366 rte_edge_t next, void *obj0, void *obj1)
367{
368 node = __rte_node_next_node_get(node, next);
369 uint16_t idx = node->idx;
370
371 __rte_node_enqueue_prologue(graph, node, idx, 2);
372
373 node->objs[idx++] = obj0;
374 node->objs[idx++] = obj1;
375 node->idx = idx;
376}
377
398static inline void
399rte_node_enqueue_x4(struct rte_graph *graph, struct rte_node *node,
400 rte_edge_t next, void *obj0, void *obj1, void *obj2,
401 void *obj3)
402{
403 node = __rte_node_next_node_get(node, next);
404 uint16_t idx = node->idx;
405
406 __rte_node_enqueue_prologue(graph, node, idx, 4);
407
408 node->objs[idx++] = obj0;
409 node->objs[idx++] = obj1;
410 node->objs[idx++] = obj2;
411 node->objs[idx++] = obj3;
412 node->idx = idx;
413}
414
431static inline void
432rte_node_enqueue_next(struct rte_graph *graph, struct rte_node *node,
433 rte_edge_t *nexts, void **objs, uint16_t nb_objs)
434{
435 uint16_t i;
436
437 for (i = 0; i < nb_objs; i++)
438 rte_node_enqueue_x1(graph, node, nexts[i], objs[i]);
439}
440
460static inline void **
461rte_node_next_stream_get(struct rte_graph *graph, struct rte_node *node,
462 rte_edge_t next, uint16_t nb_objs)
463{
464 node = __rte_node_next_node_get(node, next);
465 const uint16_t idx = node->idx;
466 uint16_t free_space = node->size - idx;
467
468 if (unlikely(free_space < nb_objs))
469 __rte_node_stream_alloc_size(graph, node, node->size + nb_objs);
470
471 return &node->objs[idx];
472}
473
490static inline void
491rte_node_next_stream_put(struct rte_graph *graph, struct rte_node *node,
492 rte_edge_t next, uint16_t idx)
493{
494 if (unlikely(!idx))
495 return;
496
497 node = __rte_node_next_node_get(node, next);
498 if (node->idx == 0)
499 __rte_node_enqueue_tail_update(graph, node);
500
501 node->idx += idx;
502}
503
518static inline void
519rte_node_next_stream_move(struct rte_graph *graph, struct rte_node *src,
520 rte_edge_t next)
521{
522 struct rte_node *dst = __rte_node_next_node_get(src, next);
523
524 /* Let swap the pointers if dst don't have valid objs */
525 if (likely(dst->idx == 0)) {
526 void **dobjs = dst->objs;
527 uint16_t dsz = dst->size;
528 dst->objs = src->objs;
529 dst->size = src->size;
530 src->objs = dobjs;
531 src->size = dsz;
532 dst->idx = src->idx;
533 __rte_node_enqueue_tail_update(graph, dst);
534 } else { /* Move the objects from src node to dst node */
535 rte_node_enqueue(graph, src, next, src->objs, src->idx);
536 }
537}
538
548bool
550
561int rte_graph_worker_model_set(uint8_t model);
562
575uint8_t rte_graph_worker_model_get(struct rte_graph *graph);
576
590uint8_t rte_graph_worker_model_no_check_get(struct rte_graph *graph)
591{
592 return graph->model;
593}
594
607__rte_experimental
608static inline void
609rte_node_xstat_increment(struct rte_node *node, uint16_t xstat_id, uint64_t value)
610{
612 uint64_t *xstat = (uint64_t *)RTE_PTR_ADD(node, node->xstat_off);
613 xstat[xstat_id] += value;
614 }
615}
616
617#ifdef __cplusplus
618}
619#endif
620
621#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
void(* packets_enqueued_cb)(struct rte_graph *graph, uint64_t cb_priv)
Definition: rte_graph.h:161
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:728
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