DPDK  24.11.0-rc3
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
28 extern "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
35 
36 #define RTE_GRAPH_MODEL_DEFAULT RTE_GRAPH_MODEL_RTC
43 SLIST_HEAD(rte_graph_rq_head, rte_graph);
44 
50 struct __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;
77  char name[RTE_GRAPH_NAMESIZE];
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 
92 struct __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  } dispatch;
114  };
115 
117  alignas(RTE_CACHE_LINE_MIN_SIZE)
118  rte_graph_off_t xstat_off;
121  __extension__ struct __rte_cache_aligned {
122 #define RTE_NODE_CTX_SZ 16
123  union {
124  uint8_t ctx[RTE_NODE_CTX_SZ];
125  __extension__ struct {
126  void *ctx_ptr;
127  void *ctx_ptr2;
128  };
129  };
130  uint16_t size;
131  uint16_t idx;
133  uint64_t total_cycles;
134  uint64_t total_calls;
135  uint64_t total_objs;
136  union {
137  void **objs;
138  uint64_t objs_u64;
139  };
140  union {
142  uint64_t process_u64;
143  };
144  alignas(RTE_CACHE_LINE_MIN_SIZE) struct rte_node *nodes[];
145  };
146 };
147 
148 static_assert(offsetof(struct rte_node, nodes) - offsetof(struct rte_node, ctx)
149  == RTE_CACHE_LINE_MIN_SIZE, "rte_node fast path area must fit in 64 bytes");
150 
163 void __rte_node_stream_alloc(struct rte_graph *graph, struct rte_node *node);
164 
179 void __rte_node_stream_alloc_size(struct rte_graph *graph,
180  struct rte_node *node, uint16_t req_size);
181 
182 /* Fast path helper functions */
183 
194 static __rte_always_inline void
195 __rte_node_process(struct rte_graph *graph, struct rte_node *node)
196 {
197  uint64_t start;
198  uint16_t rc;
199  void **objs;
200 
201  RTE_ASSERT(node->fence == RTE_GRAPH_FENCE);
202  objs = node->objs;
203  rte_prefetch0(objs);
204 
206  start = rte_rdtsc();
207  rc = node->process(graph, node, objs, node->idx);
208  node->total_cycles += rte_rdtsc() - start;
209  node->total_calls++;
210  node->total_objs += rc;
211  } else {
212  node->process(graph, node, objs, node->idx);
213  }
214  node->idx = 0;
215 }
216 
227 static __rte_always_inline void
228 __rte_node_enqueue_tail_update(struct rte_graph *graph, struct rte_node *node)
229 {
230  uint32_t tail;
231 
232  tail = graph->tail;
233  graph->cir_start[tail++] = node->off;
234  graph->tail = tail & graph->cir_mask;
235 }
236 
254 static __rte_always_inline void
255 __rte_node_enqueue_prologue(struct rte_graph *graph, struct rte_node *node,
256  const uint16_t idx, const uint16_t space)
257 {
258 
259  /* Add to the pending stream list if the node is new */
260  if (idx == 0)
261  __rte_node_enqueue_tail_update(graph, node);
262 
263  if (unlikely(node->size < (idx + space)))
264  __rte_node_stream_alloc_size(graph, node, node->size + space);
265 }
266 
280 static __rte_always_inline struct rte_node *
281 __rte_node_next_node_get(struct rte_node *node, rte_edge_t next)
282 {
283  RTE_ASSERT(next < node->nb_edges);
284  RTE_ASSERT(node->fence == RTE_GRAPH_FENCE);
285  node = node->nodes[next];
286  RTE_ASSERT(node->fence == RTE_GRAPH_FENCE);
287 
288  return node;
289 }
290 
306 static inline void
307 rte_node_enqueue(struct rte_graph *graph, struct rte_node *node,
308  rte_edge_t next, void **objs, uint16_t nb_objs)
309 {
310  node = __rte_node_next_node_get(node, next);
311  const uint16_t idx = node->idx;
312 
313  __rte_node_enqueue_prologue(graph, node, idx, nb_objs);
314 
315  rte_memcpy(&node->objs[idx], objs, nb_objs * sizeof(void *));
316  node->idx = idx + nb_objs;
317 }
318 
332 static inline void
333 rte_node_enqueue_x1(struct rte_graph *graph, struct rte_node *node,
334  rte_edge_t next, void *obj)
335 {
336  node = __rte_node_next_node_get(node, next);
337  uint16_t idx = node->idx;
338 
339  __rte_node_enqueue_prologue(graph, node, idx, 1);
340 
341  node->objs[idx++] = obj;
342  node->idx = idx;
343 }
344 
361 static inline void
362 rte_node_enqueue_x2(struct rte_graph *graph, struct rte_node *node,
363  rte_edge_t next, void *obj0, void *obj1)
364 {
365  node = __rte_node_next_node_get(node, next);
366  uint16_t idx = node->idx;
367 
368  __rte_node_enqueue_prologue(graph, node, idx, 2);
369 
370  node->objs[idx++] = obj0;
371  node->objs[idx++] = obj1;
372  node->idx = idx;
373 }
374 
395 static inline void
396 rte_node_enqueue_x4(struct rte_graph *graph, struct rte_node *node,
397  rte_edge_t next, void *obj0, void *obj1, void *obj2,
398  void *obj3)
399 {
400  node = __rte_node_next_node_get(node, next);
401  uint16_t idx = node->idx;
402 
403  __rte_node_enqueue_prologue(graph, node, idx, 4);
404 
405  node->objs[idx++] = obj0;
406  node->objs[idx++] = obj1;
407  node->objs[idx++] = obj2;
408  node->objs[idx++] = obj3;
409  node->idx = idx;
410 }
411 
428 static inline void
429 rte_node_enqueue_next(struct rte_graph *graph, struct rte_node *node,
430  rte_edge_t *nexts, void **objs, uint16_t nb_objs)
431 {
432  uint16_t i;
433 
434  for (i = 0; i < nb_objs; i++)
435  rte_node_enqueue_x1(graph, node, nexts[i], objs[i]);
436 }
437 
457 static inline void **
458 rte_node_next_stream_get(struct rte_graph *graph, struct rte_node *node,
459  rte_edge_t next, uint16_t nb_objs)
460 {
461  node = __rte_node_next_node_get(node, next);
462  const uint16_t idx = node->idx;
463  uint16_t free_space = node->size - idx;
464 
465  if (unlikely(free_space < nb_objs))
466  __rte_node_stream_alloc_size(graph, node, node->size + nb_objs);
467 
468  return &node->objs[idx];
469 }
470 
487 static inline void
488 rte_node_next_stream_put(struct rte_graph *graph, struct rte_node *node,
489  rte_edge_t next, uint16_t idx)
490 {
491  if (unlikely(!idx))
492  return;
493 
494  node = __rte_node_next_node_get(node, next);
495  if (node->idx == 0)
496  __rte_node_enqueue_tail_update(graph, node);
497 
498  node->idx += idx;
499 }
500 
515 static inline void
516 rte_node_next_stream_move(struct rte_graph *graph, struct rte_node *src,
517  rte_edge_t next)
518 {
519  struct rte_node *dst = __rte_node_next_node_get(src, next);
520 
521  /* Let swap the pointers if dst don't have valid objs */
522  if (likely(dst->idx == 0)) {
523  void **dobjs = dst->objs;
524  uint16_t dsz = dst->size;
525  dst->objs = src->objs;
526  dst->size = src->size;
527  src->objs = dobjs;
528  src->size = dsz;
529  dst->idx = src->idx;
530  __rte_node_enqueue_tail_update(graph, dst);
531  } else { /* Move the objects from src node to dst node */
532  rte_node_enqueue(graph, src, next, src->objs, src->idx);
533  }
534 }
535 
545 bool
546 rte_graph_model_is_valid(uint8_t model);
547 
558 int rte_graph_worker_model_set(uint8_t model);
559 
572 uint8_t rte_graph_worker_model_get(struct rte_graph *graph);
573 
586 static __rte_always_inline
587 uint8_t rte_graph_worker_model_no_check_get(struct rte_graph *graph)
588 {
589  return graph->model;
590 }
591 
604 __rte_experimental
605 static inline void
606 rte_node_xstat_increment(struct rte_node *node, uint16_t xstat_id, uint64_t value)
607 {
609  uint64_t *xstat = (uint64_t *)RTE_PTR_ADD(node, node->xstat_off);
610  xstat[xstat_id] += value;
611  }
612 }
613 
614 #ifdef __cplusplus
615 }
616 #endif
617 
618 #endif /* _RTE_GRAPH_WORKER_COIMMON_H_ */
uint32_t rte_node_t
Definition: rte_graph.h:41
#define __rte_always_inline
Definition: rte_common.h:413
bool rte_graph_model_is_valid(uint8_t model)
uint16_t rte_edge_t
Definition: rte_graph.h:42
static void rte_node_enqueue(struct rte_graph *graph, struct rte_node *node, rte_edge_t next, void **objs, uint16_t nb_objs)
#define likely(x)
int rte_graph_worker_model_set(uint8_t model)
static __rte_experimental void rte_node_xstat_increment(struct rte_node *node, uint16_t xstat_id, uint64_t value)
#define RTE_NODE_NAMESIZE
Definition: rte_graph.h:31
#define RTE_GRAPH_PCAP_FILE_SZ
Definition: rte_graph.h:33
static __rte_always_inline int rte_graph_has_stats_feature(void)
Definition: rte_graph.h:701
static __rte_always_inline uint8_t rte_graph_worker_model_no_check_get(struct rte_graph *graph)
uint16_t rte_graph_t
Definition: rte_graph.h:43
uint16_t(* rte_node_process_t)(struct rte_graph *graph, struct rte_node *node, void **objs, uint16_t nb_objs)
Definition: rte_graph.h:94
static void rte_node_enqueue_x1(struct rte_graph *graph, struct rte_node *node, rte_edge_t next, void *obj)
#define RTE_GRAPH_NAMESIZE
Definition: rte_graph.h:30
static void ** rte_node_next_stream_get(struct rte_graph *graph, struct rte_node *node, rte_edge_t next, uint16_t nb_objs)
#define __rte_cache_aligned
Definition: rte_common.h:627
char name[RTE_MEMPOOL_NAMESIZE]
Definition: rte_mempool.h:231
#define offsetof(TYPE, MEMBER)
Definition: rte_common.h:724
static void rte_node_next_stream_move(struct rte_graph *graph, struct rte_node *src, rte_edge_t next)
#define RTE_PTR_ADD(ptr, x)
Definition: rte_common.h:469
#define unlikely(x)
static void rte_node_enqueue_x2(struct rte_graph *graph, struct rte_node *node, rte_edge_t next, void *obj0, void *obj1)
static void rte_node_next_stream_put(struct rte_graph *graph, struct rte_node *node, rte_edge_t next, uint16_t idx)
#define RTE_GRAPH_FENCE
Definition: rte_graph.h:38
#define RTE_CACHE_LINE_MIN_SIZE
Definition: rte_common.h:624
static void rte_node_enqueue_next(struct rte_graph *graph, struct rte_node *node, rte_edge_t *nexts, void **objs, uint16_t nb_objs)
uint8_t rte_graph_worker_model_get(struct rte_graph *graph)
uint32_t rte_graph_off_t
Definition: rte_graph.h:40
static void * rte_memcpy(void *dst, const void *src, size_t n)
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)
static void rte_prefetch0(const volatile void *p)