DPDK 26.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 rte_node_t nb_nodes;
53 rte_graph_off_t nodes_start;
54 rte_graph_off_t *sched_table;
55 uint64_t *pending;
56 uint64_t *src_pending;
57 uint16_t nb_sched_words;
58 uint8_t model;
59 /* 26 bytes padding */
60 union {
61 /* Fast schedule area for mcore dispatch model */
62 struct {
63 alignas(RTE_CACHE_LINE_SIZE) struct rte_graph_rq_head *rq;
64 /* The run-queue */
65 struct rte_graph_rq_head rq_head; /* The head for run-queue list */
66
67 unsigned int lcore_id;
68 struct rte_ring *wq;
69 struct rte_mempool *mp;
70 packets_enqueued_cb notify_cb;
71 uint64_t cb_priv;
72 } dispatch;
73 };
74 SLIST_ENTRY(rte_graph) next; /* The next for rte_graph list */
75 /* End of Fast path area.*/
76 rte_graph_t id;
77 int socket;
79 bool pcap_enable;
81 uint64_t nb_pkt_captured;
83 uint64_t nb_pkt_to_capture;
84 char pcap_filename[RTE_GRAPH_PCAP_FILE_SZ];
85 uint64_t fence;
86};
87
93struct __rte_cache_aligned rte_node {
94 /* Slow path area */
95 uint64_t fence;
96 rte_graph_off_t next;
97 rte_node_t id;
98 rte_node_t parent_id;
99 rte_edge_t nb_edges;
100 uint16_t sched_idx;
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#ifdef RTE_GRAPH_PROFILE
127 struct {
128 uint64_t calls;
129 uint64_t cycles;
130 } usage_stats_01[2];
138 struct {
139 uint64_t calls;
140 uint64_t cycles;
141 uint64_t objs;
142 } usage_stats[4];
144#endif
145 __extension__ struct __rte_cache_aligned {
146#define RTE_NODE_CTX_SZ 16
147 union {
148 uint8_t ctx[RTE_NODE_CTX_SZ];
149 __extension__ struct {
150 void *ctx_ptr;
151 void *ctx_ptr2;
152 };
153 };
154 uint16_t size;
155 uint16_t idx;
157 uint64_t total_cycles;
158 uint64_t total_calls;
159 uint64_t total_objs;
160 union {
161 void **objs;
162 uint64_t objs_u64;
163 };
164 union {
166 uint64_t process_u64;
167 };
168 alignas(RTE_CACHE_LINE_MIN_SIZE) struct rte_node *nodes[];
169 };
170};
171
172#ifndef RTE_GRAPH_PROFILE
173static_assert(offsetof(struct rte_node, nodes) - offsetof(struct rte_node, ctx)
174 == RTE_CACHE_LINE_MIN_SIZE, "rte_node fast path area must fit in 64 bytes");
175#endif
176
189void __rte_node_stream_alloc(struct rte_graph *graph, struct rte_node *node);
190
205void __rte_node_stream_alloc_size(struct rte_graph *graph,
206 struct rte_node *node, uint16_t req_size);
207
208/* Fast path helper functions */
209
220static __rte_always_inline void
221__rte_node_process(struct rte_graph *graph, struct rte_node *node)
222{
223 uint64_t cycles;
224 uint16_t rc;
225 void **objs;
226
227 RTE_ASSERT(node->fence == RTE_GRAPH_FENCE);
228 objs = node->objs;
229 rte_prefetch0(objs);
230
232 cycles = rte_rdtsc();
233 rc = node->process(graph, node, objs, node->idx);
234 cycles = rte_rdtsc() - cycles;
235 node->total_cycles += cycles;
236 node->total_calls++;
237 node->total_objs += rc;
238#ifdef RTE_GRAPH_PROFILE
239 static_assert(RTE_GRAPH_PROFILE_BURST_SMALL >= 2,
240 "BURST_SMALL must be >= 2");
241 static_assert(RTE_GRAPH_PROFILE_BURST_SMALL < RTE_GRAPH_PROFILE_BURST_MEDIUM,
242 "BURST_SMALL must be < BURST_MEDIUM");
243 static_assert(RTE_GRAPH_PROFILE_BURST_MEDIUM < RTE_GRAPH_PROFILE_BURST_LARGE,
244 "BURST_MEDIUM must be < BURST_LARGE");
245 if (rc < 2) {
246 node->usage_stats_01[rc].calls++;
247 node->usage_stats_01[rc].cycles += cycles;
248 } else {
249 unsigned int index;
250
251 if (rc >= RTE_GRAPH_PROFILE_BURST_LARGE)
252 index = 3;
253 else if (rc >= RTE_GRAPH_PROFILE_BURST_MEDIUM)
254 index = 2;
255 else if (rc >= RTE_GRAPH_PROFILE_BURST_SMALL)
256 index = 1;
257 else
258 index = 0;
259
260 node->usage_stats[index].calls++;
261 node->usage_stats[index].cycles += cycles;
262 node->usage_stats[index].objs += rc;
263 }
264#endif
265 } else {
266 node->process(graph, node, objs, node->idx);
267 }
268 node->idx = 0;
269}
270
286static inline struct rte_node *
287__rte_graph_pending_node(struct rte_graph *graph, uint16_t word, uint16_t bit)
288{
289 const uint16_t index = (word * sizeof(*graph->pending) * CHAR_BIT) + bit;
290 const rte_graph_off_t node_offset = graph->sched_table[index];
291 return (struct rte_node *)RTE_PTR_ADD(graph, node_offset);
292}
293
304static inline void
305__rte_node_pending_set(uint64_t *bitmap, struct rte_node *node)
306{
307 const uint16_t word = node->sched_idx / (sizeof(*bitmap) * CHAR_BIT);
308 const uint16_t bit = node->sched_idx % (sizeof(*bitmap) * CHAR_BIT);
309 bitmap[word] |= 1ULL << bit;
310}
311
329static __rte_always_inline void
330__rte_node_enqueue_prologue(struct rte_graph *graph, struct rte_node *node,
331 const uint16_t idx, const uint16_t space)
332{
333
334 if (idx == 0)
335 __rte_node_pending_set(graph->pending, node);
336
337 if (unlikely(node->size < (idx + space)))
338 __rte_node_stream_alloc_size(graph, node, node->size + space);
339}
340
354static __rte_always_inline struct rte_node *
355__rte_node_next_node_get(struct rte_node *node, rte_edge_t next)
356{
357 RTE_ASSERT(next < node->nb_edges);
358 RTE_ASSERT(node->fence == RTE_GRAPH_FENCE);
359 node = node->nodes[next];
360 RTE_ASSERT(node->fence == RTE_GRAPH_FENCE);
361
362 return node;
363}
364
380static inline void
381rte_node_enqueue(struct rte_graph *graph, struct rte_node *node,
382 rte_edge_t next, void **objs, uint16_t nb_objs)
383{
384 node = __rte_node_next_node_get(node, next);
385 const uint16_t idx = node->idx;
386
387 __rte_node_enqueue_prologue(graph, node, idx, nb_objs);
388
389 rte_memcpy(&node->objs[idx], objs, nb_objs * sizeof(void *));
390 node->idx = idx + nb_objs;
391}
392
406static inline void
407rte_node_enqueue_x1(struct rte_graph *graph, struct rte_node *node,
408 rte_edge_t next, void *obj)
409{
410 node = __rte_node_next_node_get(node, next);
411 uint16_t idx = node->idx;
412
413 __rte_node_enqueue_prologue(graph, node, idx, 1);
414
415 node->objs[idx++] = obj;
416 node->idx = idx;
417}
418
435static inline void
436rte_node_enqueue_x2(struct rte_graph *graph, struct rte_node *node,
437 rte_edge_t next, void *obj0, void *obj1)
438{
439 node = __rte_node_next_node_get(node, next);
440 uint16_t idx = node->idx;
441
442 __rte_node_enqueue_prologue(graph, node, idx, 2);
443
444 node->objs[idx++] = obj0;
445 node->objs[idx++] = obj1;
446 node->idx = idx;
447}
448
469static inline void
470rte_node_enqueue_x4(struct rte_graph *graph, struct rte_node *node,
471 rte_edge_t next, void *obj0, void *obj1, void *obj2,
472 void *obj3)
473{
474 node = __rte_node_next_node_get(node, next);
475 uint16_t idx = node->idx;
476
477 __rte_node_enqueue_prologue(graph, node, idx, 4);
478
479 node->objs[idx++] = obj0;
480 node->objs[idx++] = obj1;
481 node->objs[idx++] = obj2;
482 node->objs[idx++] = obj3;
483 node->idx = idx;
484}
485
502static inline void
503rte_node_enqueue_next(struct rte_graph *graph, struct rte_node *node,
504 rte_edge_t *nexts, void **objs, uint16_t nb_objs)
505{
506 uint16_t i;
507
508 for (i = 0; i < nb_objs; i++)
509 rte_node_enqueue_x1(graph, node, nexts[i], objs[i]);
510}
511
531static inline void **
532rte_node_next_stream_get(struct rte_graph *graph, struct rte_node *node,
533 rte_edge_t next, uint16_t nb_objs)
534{
535 node = __rte_node_next_node_get(node, next);
536 const uint16_t idx = node->idx;
537 uint16_t free_space = node->size - idx;
538
539 if (unlikely(free_space < nb_objs))
540 __rte_node_stream_alloc_size(graph, node, node->size + nb_objs);
541
542 return &node->objs[idx];
543}
544
561static inline void
562rte_node_next_stream_put(struct rte_graph *graph, struct rte_node *node,
563 rte_edge_t next, uint16_t idx)
564{
565 if (unlikely(!idx))
566 return;
567
568 node = __rte_node_next_node_get(node, next);
569 if (node->idx == 0)
570 __rte_node_pending_set(graph->pending, node);
571
572 node->idx += idx;
573}
574
589static inline void
590rte_node_next_stream_move(struct rte_graph *graph, struct rte_node *src,
591 rte_edge_t next)
592{
593 struct rte_node *dst = __rte_node_next_node_get(src, next);
594
595 /* Let swap the pointers if dst don't have valid objs */
596 if (likely(dst->idx == 0)) {
597 void **dobjs = dst->objs;
598 uint16_t dsz = dst->size;
599 dst->objs = src->objs;
600 dst->size = src->size;
601 src->objs = dobjs;
602 src->size = dsz;
603 dst->idx = src->idx;
604 __rte_node_pending_set(graph->pending, dst);
605 } else { /* Move the objects from src node to dst node */
606 rte_node_enqueue(graph, src, next, src->objs, src->idx);
607 }
608}
609
619bool
621
632int rte_graph_worker_model_set(uint8_t model);
633
646uint8_t rte_graph_worker_model_get(struct rte_graph *graph);
647
661uint8_t rte_graph_worker_model_no_check_get(struct rte_graph *graph)
662{
663 return graph->model;
664}
665
678__rte_experimental
679static inline void
680rte_node_xstat_increment(struct rte_node *node, uint16_t xstat_id, uint64_t value)
681{
683 uint64_t *xstat = (uint64_t *)RTE_PTR_ADD(node, node->xstat_off);
684 xstat[xstat_id] += value;
685 }
686}
687
688#ifdef __cplusplus
689}
690#endif
691
692#endif /* _RTE_GRAPH_WORKER_COIMMON_H_ */
#define likely(x)
#define unlikely(x)
#define RTE_CACHE_LINE_MIN_SIZE
Definition: rte_common.h:936
#define offsetof(TYPE, MEMBER)
Definition: rte_common.h:1066
#define RTE_PTR_ADD(ptr, x)
Definition: rte_common.h:643
#define __rte_cache_aligned
Definition: rte_common.h:939
#define __rte_always_inline
Definition: rte_common.h:534
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:240