DPDK  23.07.0
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 
19 #include <rte_compat.h>
20 #include <rte_common.h>
21 #include <rte_cycles.h>
22 #include <rte_prefetch.h>
23 #include <rte_memcpy.h>
24 #include <rte_memory.h>
25 
26 #include "rte_graph.h"
27 
28 #ifdef __cplusplus
29 extern "C" {
30 #endif
31 
33 /* When adding a new graph model entry, update rte_graph_model_is_valid() implementation. */
34 #define RTE_GRAPH_MODEL_RTC 0
35 #define RTE_GRAPH_MODEL_MCORE_DISPATCH 1
36 
37 #define RTE_GRAPH_MODEL_DEFAULT RTE_GRAPH_MODEL_RTC
44 SLIST_HEAD(rte_graph_rq_head, rte_graph);
45 
51 struct rte_graph {
52  /* Fast path area. */
53  uint32_t tail;
54  uint32_t head;
55  uint32_t cir_mask;
56  rte_node_t nb_nodes;
57  rte_graph_off_t *cir_start;
58  rte_graph_off_t nodes_start;
59  uint8_t model;
60  uint8_t reserved1;
61  uint16_t reserved2;
63  union {
64  /* Fast schedule area for mcore dispatch model */
65  struct {
66  struct rte_graph_rq_head *rq __rte_cache_aligned; /* The run-queue */
67  struct rte_graph_rq_head rq_head; /* The head for run-queue list */
68 
69  unsigned int lcore_id;
70  struct rte_ring *wq;
71  struct rte_mempool *mp;
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;
78  char name[RTE_GRAPH_NAMESIZE];
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;
87 
93 struct 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  uint32_t realloc_count;
102  char parent[RTE_NODE_NAMESIZE];
103  char name[RTE_NODE_NAMESIZE];
106  rte_node_process_t original_process;
107 
109  union {
110  /* Fast schedule area for mcore dispatch model */
111  struct {
112  unsigned int lcore_id;
113  uint64_t total_sched_objs;
114  uint64_t total_sched_fail;
115  } dispatch;
116  };
117  /* Fast path area */
118 #define RTE_NODE_CTX_SZ 16
119  uint8_t ctx[RTE_NODE_CTX_SZ] __rte_cache_aligned;
120  uint16_t size;
121  uint16_t idx;
122  rte_graph_off_t off;
123  uint64_t total_cycles;
124  uint64_t total_calls;
125  uint64_t total_objs;
127  union {
128  void **objs;
129  uint64_t objs_u64;
130  };
132  union {
133  rte_node_process_t process;
134  uint64_t process_u64;
135  };
136  struct rte_node *nodes[] __rte_cache_min_aligned;
138 
151 __rte_experimental
152 void __rte_node_stream_alloc(struct rte_graph *graph, struct rte_node *node);
153 
168 __rte_experimental
169 void __rte_node_stream_alloc_size(struct rte_graph *graph,
170  struct rte_node *node, uint16_t req_size);
171 
172 /* Fast path helper functions */
173 
184 static __rte_always_inline void
185 __rte_node_process(struct rte_graph *graph, struct rte_node *node)
186 {
187  uint64_t start;
188  uint16_t rc;
189  void **objs;
190 
191  RTE_ASSERT(node->fence == RTE_GRAPH_FENCE);
192  objs = node->objs;
193  rte_prefetch0(objs);
194 
196  start = rte_rdtsc();
197  rc = node->process(graph, node, objs, node->idx);
198  node->total_cycles += rte_rdtsc() - start;
199  node->total_calls++;
200  node->total_objs += rc;
201  } else {
202  node->process(graph, node, objs, node->idx);
203  }
204  node->idx = 0;
205 }
206 
217 static __rte_always_inline void
218 __rte_node_enqueue_tail_update(struct rte_graph *graph, struct rte_node *node)
219 {
220  uint32_t tail;
221 
222  tail = graph->tail;
223  graph->cir_start[tail++] = node->off;
224  graph->tail = tail & graph->cir_mask;
225 }
226 
244 static __rte_always_inline void
245 __rte_node_enqueue_prologue(struct rte_graph *graph, struct rte_node *node,
246  const uint16_t idx, const uint16_t space)
247 {
248 
249  /* Add to the pending stream list if the node is new */
250  if (idx == 0)
251  __rte_node_enqueue_tail_update(graph, node);
252 
253  if (unlikely(node->size < (idx + space)))
254  __rte_node_stream_alloc_size(graph, node, node->size + space);
255 }
256 
270 static __rte_always_inline struct rte_node *
271 __rte_node_next_node_get(struct rte_node *node, rte_edge_t next)
272 {
273  RTE_ASSERT(next < node->nb_edges);
274  RTE_ASSERT(node->fence == RTE_GRAPH_FENCE);
275  node = node->nodes[next];
276  RTE_ASSERT(node->fence == RTE_GRAPH_FENCE);
277 
278  return node;
279 }
280 
296 __rte_experimental
297 static inline void
298 rte_node_enqueue(struct rte_graph *graph, struct rte_node *node,
299  rte_edge_t next, void **objs, uint16_t nb_objs)
300 {
301  node = __rte_node_next_node_get(node, next);
302  const uint16_t idx = node->idx;
303 
304  __rte_node_enqueue_prologue(graph, node, idx, nb_objs);
305 
306  rte_memcpy(&node->objs[idx], objs, nb_objs * sizeof(void *));
307  node->idx = idx + nb_objs;
308 }
309 
323 __rte_experimental
324 static inline void
325 rte_node_enqueue_x1(struct rte_graph *graph, struct rte_node *node,
326  rte_edge_t next, void *obj)
327 {
328  node = __rte_node_next_node_get(node, next);
329  uint16_t idx = node->idx;
330 
331  __rte_node_enqueue_prologue(graph, node, idx, 1);
332 
333  node->objs[idx++] = obj;
334  node->idx = idx;
335 }
336 
353 __rte_experimental
354 static inline void
355 rte_node_enqueue_x2(struct rte_graph *graph, struct rte_node *node,
356  rte_edge_t next, void *obj0, void *obj1)
357 {
358  node = __rte_node_next_node_get(node, next);
359  uint16_t idx = node->idx;
360 
361  __rte_node_enqueue_prologue(graph, node, idx, 2);
362 
363  node->objs[idx++] = obj0;
364  node->objs[idx++] = obj1;
365  node->idx = idx;
366 }
367 
388 __rte_experimental
389 static inline void
390 rte_node_enqueue_x4(struct rte_graph *graph, struct rte_node *node,
391  rte_edge_t next, void *obj0, void *obj1, void *obj2,
392  void *obj3)
393 {
394  node = __rte_node_next_node_get(node, next);
395  uint16_t idx = node->idx;
396 
397  __rte_node_enqueue_prologue(graph, node, idx, 4);
398 
399  node->objs[idx++] = obj0;
400  node->objs[idx++] = obj1;
401  node->objs[idx++] = obj2;
402  node->objs[idx++] = obj3;
403  node->idx = idx;
404 }
405 
422 __rte_experimental
423 static inline void
424 rte_node_enqueue_next(struct rte_graph *graph, struct rte_node *node,
425  rte_edge_t *nexts, void **objs, uint16_t nb_objs)
426 {
427  uint16_t i;
428 
429  for (i = 0; i < nb_objs; i++)
430  rte_node_enqueue_x1(graph, node, nexts[i], objs[i]);
431 }
432 
452 __rte_experimental
453 static inline void **
454 rte_node_next_stream_get(struct rte_graph *graph, struct rte_node *node,
455  rte_edge_t next, uint16_t nb_objs)
456 {
457  node = __rte_node_next_node_get(node, next);
458  const uint16_t idx = node->idx;
459  uint16_t free_space = node->size - idx;
460 
461  if (unlikely(free_space < nb_objs))
462  __rte_node_stream_alloc_size(graph, node, node->size + nb_objs);
463 
464  return &node->objs[idx];
465 }
466 
483 __rte_experimental
484 static inline void
485 rte_node_next_stream_put(struct rte_graph *graph, struct rte_node *node,
486  rte_edge_t next, uint16_t idx)
487 {
488  if (unlikely(!idx))
489  return;
490 
491  node = __rte_node_next_node_get(node, next);
492  if (node->idx == 0)
493  __rte_node_enqueue_tail_update(graph, node);
494 
495  node->idx += idx;
496 }
497 
512 __rte_experimental
513 static inline void
514 rte_node_next_stream_move(struct rte_graph *graph, struct rte_node *src,
515  rte_edge_t next)
516 {
517  struct rte_node *dst = __rte_node_next_node_get(src, next);
518 
519  /* Let swap the pointers if dst don't have valid objs */
520  if (likely(dst->idx == 0)) {
521  void **dobjs = dst->objs;
522  uint16_t dsz = dst->size;
523  dst->objs = src->objs;
524  dst->size = src->size;
525  src->objs = dobjs;
526  src->size = dsz;
527  dst->idx = src->idx;
528  __rte_node_enqueue_tail_update(graph, dst);
529  } else { /* Move the objects from src node to dst node */
530  rte_node_enqueue(graph, src, next, src->objs, src->idx);
531  }
532 }
533 
543 __rte_experimental
544 bool
545 rte_graph_model_is_valid(uint8_t model);
546 
557 __rte_experimental
558 int rte_graph_worker_model_set(uint8_t model);
559 
572 __rte_experimental
573 uint8_t rte_graph_worker_model_get(struct rte_graph *graph);
574 
587 __rte_experimental
588 static __rte_always_inline
589 uint8_t rte_graph_worker_model_no_check_get(struct rte_graph *graph)
590 {
591  return graph->model;
592 }
593 
594 #ifdef __cplusplus
595 }
596 #endif
597 
598 #endif /* _RTE_GRAPH_WORKER_COIMMON_H_ */
uint32_t rte_node_t
Definition: rte_graph.h:45
#define __rte_always_inline
Definition: rte_common.h:255
uint16_t rte_edge_t
Definition: rte_graph.h:46
static __rte_experimental void ** rte_node_next_stream_get(struct rte_graph *graph, struct rte_node *node, rte_edge_t next, uint16_t nb_objs)
__rte_experimental uint8_t rte_graph_worker_model_get(struct rte_graph *graph)
#define __rte_cache_min_aligned
Definition: rte_common.h:443
#define likely(x)
static __rte_experimental void rte_node_enqueue_x1(struct rte_graph *graph, struct rte_node *node, rte_edge_t next, void *obj)
#define RTE_NODE_NAMESIZE
Definition: rte_graph.h:36
#define RTE_GRAPH_PCAP_FILE_SZ
Definition: rte_graph.h:37
static __rte_always_inline int rte_graph_has_stats_feature(void)
Definition: rte_graph.h:724
uint16_t rte_graph_t
Definition: rte_graph.h:47
uint16_t(* rte_node_process_t)(struct rte_graph *graph, struct rte_node *node, void **objs, uint16_t nb_objs)
Definition: rte_graph.h:98
#define RTE_GRAPH_NAMESIZE
Definition: rte_graph.h:35
static __rte_experimental void rte_node_next_stream_move(struct rte_graph *graph, struct rte_node *src, rte_edge_t next)
char name[RTE_MEMPOOL_NAMESIZE]
Definition: rte_mempool.h:220
#define unlikely(x)
static __rte_experimental 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)
#define RTE_GRAPH_FENCE
Definition: rte_graph.h:42
static __rte_experimental void rte_node_enqueue_x2(struct rte_graph *graph, struct rte_node *node, rte_edge_t next, void *obj0, void *obj1)
static __rte_experimental void rte_node_enqueue_next(struct rte_graph *graph, struct rte_node *node, rte_edge_t *nexts, void **objs, uint16_t nb_objs)
__rte_experimental bool rte_graph_model_is_valid(uint8_t model)
#define __rte_cache_aligned
Definition: rte_common.h:440
#define RTE_STD_C11
Definition: rte_common.h:39
static __rte_experimental void rte_node_enqueue(struct rte_graph *graph, struct rte_node *node, rte_edge_t next, void **objs, uint16_t nb_objs)
uint32_t rte_graph_off_t
Definition: rte_graph.h:44
static __rte_experimental __rte_always_inline uint8_t rte_graph_worker_model_no_check_get(struct rte_graph *graph)
static void * rte_memcpy(void *dst, const void *src, size_t n)
__rte_experimental int rte_graph_worker_model_set(uint8_t model)
static __rte_experimental void rte_node_next_stream_put(struct rte_graph *graph, struct rte_node *node, rte_edge_t next, uint16_t idx)
static void rte_prefetch0(const volatile void *p)