DPDK  25.11.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 
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
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  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;
79  char name[RTE_GRAPH_NAMESIZE];
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 
94 struct __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 
120  alignas(RTE_CACHE_LINE_MIN_SIZE)
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 
151 static_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 
166 void __rte_node_stream_alloc(struct rte_graph *graph, struct rte_node *node);
167 
182 void __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 
197 static __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 
230 static __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 
257 static __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 
283 static __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 
309 static inline void
310 rte_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 
335 static inline void
336 rte_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 
364 static inline void
365 rte_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 
398 static inline void
399 rte_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 
431 static inline void
432 rte_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 
460 static inline void **
461 rte_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 
490 static inline void
491 rte_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 
518 static inline void
519 rte_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 
548 bool
550 
561 int rte_graph_worker_model_set(uint8_t model);
562 
575 uint8_t rte_graph_worker_model_get(struct rte_graph *graph);
576 
589 static __rte_always_inline
590 uint8_t rte_graph_worker_model_no_check_get(struct rte_graph *graph)
591 {
592  return graph->model;
593 }
594 
607 __rte_experimental
608 static inline void
609 rte_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_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_node_next_stream_get(struct rte_graph *graph, struct rte_node *node, rte_edge_t next, uint16_t nb_objs)
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