FD.io VPP  v21.10.1-2-g0a485f517
Vector Packet Processing
dequeue.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: Apache-2.0
2  * Copyright(c) 2021 Cisco Systems, Inc.
3  */
4 
5 #include <vlib/vlib.h>
6 #include <vnet/feature/feature.h>
7 #include <snort/snort.h>
8 
9 typedef struct
10 {
14 
15 static u8 *
16 format_snort_deq_trace (u8 *s, va_list *args)
17 {
18  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
19  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
20  snort_deq_trace_t *t = va_arg (*args, snort_deq_trace_t *);
21 
22  s = format (s, "snort-deq: sw_if_index %d, next index %d\n", t->sw_if_index,
23  t->next_index);
24 
25  return s;
26 }
27 
28 #define foreach_snort_deq_error \
29  _ (BAD_DESC, "bad descriptor") \
30  _ (BAD_DESC_INDEX, "bad descriptor index")
31 
32 typedef enum
33 {
34 #define _(sym, str) SNORT_DEQ_ERROR_##sym,
36 #undef _
39 
40 static char *snort_deq_error_strings[] = {
41 #define _(sym, string) string,
43 #undef _
44 };
45 
48  u32 *buffer_indices, u16 *nexts, u32 max_recv)
49 {
50  snort_main_t *sm = &snort_main;
54  u32 head, next, n_recv = 0, n_left;
55 
56  head = __atomic_load_n (qp->deq_head, __ATOMIC_ACQUIRE);
57  next = qp->next_desc;
58 
59  n_left = head - next;
60 
61  if (n_left == 0)
62  return 0;
63 
64  if (n_left > max_recv)
65  {
66  n_left = max_recv;
67  clib_interrupt_set (ptd->interrupts, instance_index);
69  }
70 
71  while (n_left)
72  {
73  u32 desc_index, bi;
74  daq_vpp_desc_t *d;
75 
76  /* check if descriptor index taken from dequqe ring is valid */
77  if ((desc_index = qp->deq_ring[next & mask]) & ~mask)
78  {
80  SNORT_DEQ_ERROR_BAD_DESC_INDEX, 1);
81  goto next;
82  }
83 
84  /* check if descriptor index taken from dequeue ring points to enqueued
85  * buffer */
86  if ((bi = qp->buffer_indices[desc_index]) == ~0)
87  {
89  SNORT_DEQ_ERROR_BAD_DESC, 1);
90  goto next;
91  }
92 
93  /* put descriptor back to freelist */
94  vec_add1 (qp->freelist, desc_index);
95  d = qp->descriptors + desc_index;
96  buffer_indices++[0] = bi;
98  nexts[0] = qp->next_indices[desc_index];
99  else
101  qp->buffer_indices[desc_index] = ~0;
102  nexts++;
103  n_recv++;
104 
105  /* next */
106  next:
107  next = next + 1;
108  n_left--;
109  }
110 
111  qp->next_desc = next;
112 
113  return n_recv;
114 }
115 
118  u32 max_recv, u8 drop_on_disconnect)
119 {
120  u32 *bi, n_processed = 0;
121  u32 desc_index = 0;
122 
123  vec_foreach (bi, qp->buffer_indices)
124  {
125  if (n_processed >= max_recv)
126  break;
127 
128  if (bi[0] == ~0)
129  continue;
130 
131  desc_index = bi - qp->buffer_indices;
132 
133  b[0] = bi[0];
134  if (drop_on_disconnect)
136  else
137  nexts[0] = qp->next_indices[desc_index];
138  qp->buffer_indices[desc_index] = ~0;
139 
140  nexts += 1;
141  b += 1;
142  n_processed += 1;
143  }
144  return n_processed;
145 }
146 
149  snort_qpair_t *qp, u32 *buffer_indices,
150  u16 *nexts, u32 max_recv,
151  u8 drop_on_disconnect)
152 {
153  snort_main_t *sm = &snort_main;
156  u32 n_processed;
157 
158  n_processed = snort_process_all_buffer_indices (
159  qp, buffer_indices, nexts, max_recv, drop_on_disconnect);
160 
161  if (n_processed == max_recv)
162  {
163  clib_interrupt_set (ptd->interrupts, instance_index);
165  }
166  else
167  {
168  *qp->enq_head = *qp->deq_head = qp->next_desc = 0;
170  __atomic_store_n (&qp->ready, 1, __ATOMIC_RELEASE);
171  }
172 
173  return n_processed;
174 }
175 
176 static u32
179 {
180  snort_main_t *sm = &snort_main;
183  u32 buffer_indices[VLIB_FRAME_SIZE], *bi = buffer_indices;
184  u16 next_indices[VLIB_FRAME_SIZE], *nexts = next_indices;
186  snort_qpair_t *qp;
188  int inst = -1;
189 
190  while ((inst = clib_interrupt_get_next (ptd->interrupts, inst)) != -1)
191  {
192  clib_interrupt_clear (ptd->interrupts, inst);
193  si = vec_elt_at_index (sm->instances, inst);
194  qp = vec_elt_at_index (si->qpairs, vm->thread_index);
195  u32 ready = __atomic_load_n (&qp->ready, __ATOMIC_ACQUIRE);
196  if (!ready)
197  n = snort_deq_instance_all_interrupt (vm, inst, qp, bi, nexts, n_left,
198  si->drop_on_disconnect);
199  else
200  n = snort_deq_instance (vm, inst, qp, bi, nexts, n_left);
201 
202  n_left -= n;
203  bi += n;
204  nexts += n;
205 
206  if (n_left == 0)
207  goto enq;
208  }
209 
210  if (n_left == VLIB_FRAME_SIZE)
211  return 0;
212 
213 enq:
214  n = VLIB_FRAME_SIZE - n_left;
215  vlib_buffer_enqueue_to_next (vm, node, buffer_indices, next_indices, n);
216  return n;
217 }
218 
221  u32 *buffer_indices, u16 *nexts, u32 max_recv)
222 {
224  u32 head, next, n_recv = 0, n_left;
225 
226  head = __atomic_load_n (qp->deq_head, __ATOMIC_ACQUIRE);
227  next = qp->next_desc;
228 
229  n_left = head - next;
230 
231  if (n_left == 0)
232  return 0;
233 
234  if (n_left > max_recv)
235  n_left = max_recv;
236 
237  while (n_left)
238  {
239  u32 desc_index, bi;
240  daq_vpp_desc_t *d;
241 
242  /* check if descriptor index taken from dequqe ring is valid */
243  if ((desc_index = qp->deq_ring[next & mask]) & ~mask)
244  {
246  SNORT_DEQ_ERROR_BAD_DESC_INDEX, 1);
247  goto next;
248  }
249 
250  /* check if descriptor index taken from dequeue ring points to enqueued
251  * buffer */
252  if ((bi = qp->buffer_indices[desc_index]) == ~0)
253  {
255  SNORT_DEQ_ERROR_BAD_DESC, 1);
256  goto next;
257  }
258 
259  /* put descriptor back to freelist */
260  vec_add1 (qp->freelist, desc_index);
261  d = qp->descriptors + desc_index;
262  buffer_indices++[0] = bi;
263  if (d->action == DAQ_VPP_ACTION_FORWARD)
264  nexts[0] = qp->next_indices[desc_index];
265  else
267  qp->buffer_indices[desc_index] = ~0;
268  nexts++;
269  n_recv++;
270 
271  /* next */
272  next:
273  next = next + 1;
274  n_left--;
275  }
276 
277  qp->next_desc = next;
278 
279  return n_recv;
280 }
281 
284  u32 *buffer_indices, u16 *nexts, u32 max_recv,
285  u8 drop_on_disconnect)
286 {
287  u32 n_processed = snort_process_all_buffer_indices (
288  qp, buffer_indices, nexts, max_recv, drop_on_disconnect);
289  if (n_processed < max_recv)
290  {
291  *qp->enq_head = *qp->deq_head = qp->next_desc = 0;
293  __atomic_store_n (&qp->ready, 1, __ATOMIC_RELEASE);
294  }
295 
296  return n_processed;
297 }
298 
299 static u32
302 {
303  snort_main_t *sm = &snort_main;
304  u32 buffer_indices[VLIB_FRAME_SIZE], *bi = buffer_indices;
305  u16 next_indices[VLIB_FRAME_SIZE], *nexts = next_indices;
306  u32 n_left = VLIB_FRAME_SIZE, n, n_total = 0;
307  snort_qpair_t *qp;
309 
310  vec_foreach (si, sm->instances)
311  {
312  qp = vec_elt_at_index (si->qpairs, vm->thread_index);
313  u32 ready = __atomic_load_n (&qp->ready, __ATOMIC_ACQUIRE);
314  if (!ready)
316  si->drop_on_disconnect);
317  else
318  n = snort_deq_instance_poll (vm, qp, bi, nexts, n_left);
319 
320  n_left -= n;
321  bi += n;
322  nexts += n;
323 
324  if (n_left == 0)
325  {
326  n = VLIB_FRAME_SIZE - n_left;
327  vlib_buffer_enqueue_to_next (vm, node, buffer_indices, next_indices,
328  n);
330  bi = buffer_indices;
331  nexts = next_indices;
332  n_total += n;
333  }
334  }
335 
336  if (n_left < VLIB_FRAME_SIZE)
337  {
338  n = VLIB_FRAME_SIZE - n_left;
339  vlib_buffer_enqueue_to_next (vm, node, buffer_indices, next_indices, n);
340  n_total += n;
341  }
342  return n_total;
343 }
344 
347 {
348  snort_main_t *sm = &snort_main;
349  if (sm->input_mode == VLIB_NODE_STATE_POLLING)
350  return snort_deq_node_polling (vm, node, frame);
352 }
353 
355  .name = "snort-deq",
356  .vector_size = sizeof (u32),
357  .format_trace = format_snort_deq_trace,
359  .state = VLIB_NODE_STATE_DISABLED,
360  .sibling_of = "snort-enq",
361 
362  .n_errors = ARRAY_LEN (snort_deq_error_strings),
363  .error_strings = snort_deq_error_strings,
364 
365  .n_next_nodes = 0,
366 };
vlib.h
snort_deq_trace_t::next_index
u32 next_index
Definition: dequeue.c:11
snort_qpair_t::freelist
u32 * freelist
Definition: snort.h:27
snort_deq_instance_all_poll
static_always_inline uword snort_deq_instance_all_poll(vlib_main_t *vm, snort_qpair_t *qp, u32 *buffer_indices, u16 *nexts, u32 max_recv, u8 drop_on_disconnect)
Definition: dequeue.c:283
SNORT_DEQ_N_ERROR
@ SNORT_DEQ_N_ERROR
Definition: dequeue.c:37
snort_qpair_t::descriptors
daq_vpp_desc_t * descriptors
Definition: snort.h:17
snort_per_thread_data_t
Definition: snort.h:64
pow2_mask
static uword pow2_mask(uword x)
Definition: clib.h:252
snort_qpair_t::buffer_indices
u32 * buffer_indices
Definition: snort.h:25
next
u16 * next
Definition: nat44_ei_out2in.c:718
VLIB_FRAME_SIZE
#define VLIB_FRAME_SIZE
Definition: node.h:368
clib_interrupt_get_next
static_always_inline int clib_interrupt_get_next(void *in, int last)
Definition: interrupt.h:104
VLIB_NODE_TYPE_INPUT
@ VLIB_NODE_TYPE_INPUT
Definition: node.h:76
snort_deq_instance_all_interrupt
static_always_inline uword snort_deq_instance_all_interrupt(vlib_main_t *vm, u32 instance_index, snort_qpair_t *qp, u32 *buffer_indices, u16 *nexts, u32 max_recv, u8 drop_on_disconnect)
Definition: dequeue.c:148
u16
unsigned short u16
Definition: types.h:57
state
vl_api_dhcp_client_state_t state
Definition: dhcp.api:201
snort.h
daq_vpp_desc_t
Definition: daq_vpp.h:68
snort_deq_node
vlib_node_registration_t snort_deq_node
(constructor) VLIB_REGISTER_NODE (snort_deq_node)
Definition: dequeue.c:354
vlib_buffer_enqueue_to_next
vlib_buffer_enqueue_to_next(vm, node, from,(u16 *) nexts, frame->n_vectors)
vlib_frame_t
Definition: node.h:372
snort_deq_error_t
snort_deq_error_t
Definition: dequeue.c:32
snort_deq_node_polling
static u32 snort_deq_node_polling(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: dequeue.c:300
snort_per_thread_data_t::interrupts
void * interrupts
Definition: snort.h:67
snort_deq_trace_t
Definition: dequeue.c:9
snort_main_t
Definition: snort.h:70
VLIB_NODE_FN
#define VLIB_NODE_FN(node)
Definition: node.h:202
feature.h
vec_add1
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:606
clib_interrupt_clear
static_always_inline void clib_interrupt_clear(void *in, int int_num)
Definition: interrupt.h:90
CLIB_UNUSED
#define CLIB_UNUSED(x)
Definition: clib.h:90
vec_elt_at_index
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
Definition: vec_bootstrap.h:203
node
vlib_main_t vlib_node_runtime_t * node
Definition: dequeue.c:346
foreach_snort_deq_error
#define foreach_snort_deq_error
Definition: dequeue.c:28
ARRAY_LEN
#define ARRAY_LEN(x)
Definition: clib.h:70
snort_main_t::instances
snort_instance_t * instances
Definition: snort.h:74
static_always_inline
#define static_always_inline
Definition: clib.h:112
uword
u64 uword
Definition: types.h:112
clib_interrupt_set
static_always_inline void clib_interrupt_set(void *in, int int_num)
Definition: interrupt.h:66
vlib_main_t::thread_index
u32 thread_index
Definition: main.h:215
vlib_node_increment_counter
static void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
Definition: node_funcs.h:1244
vm
vlib_main_t * vm
Definition: dequeue.c:346
mask
vl_api_pnat_mask_t mask
Definition: pnat.api:45
snort_freelist_init
static void snort_freelist_init(u32 *fl)
Definition: snort.h:107
snort_main_t::per_thread_data
snort_per_thread_data_t * per_thread_data
Definition: snort.h:78
snort_qpair_t::enq_head
volatile u32 * enq_head
Definition: snort.h:18
vlib_node_registration_t
struct _vlib_node_registration vlib_node_registration_t
snort_deq_trace_t::sw_if_index
u32 sw_if_index
Definition: dequeue.c:12
daq_vpp_desc_t::action
daq_vpp_action_t action
Definition: daq_vpp.h:74
snort_main_t::input_mode
u32 input_mode
Definition: snort.h:79
snort_qpair_t::next_indices
u16 * next_indices
Definition: snort.h:26
frame
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: dequeue.c:347
snort_instance_t
Definition: snort.h:37
format
description fragment has unexpected format
Definition: map.api:433
snort_qpair_t
Definition: snort.h:13
u32
unsigned int u32
Definition: types.h:88
vlib_node_set_interrupt_pending
static void vlib_node_set_interrupt_pending(vlib_main_t *vm, u32 node_index)
Definition: node_funcs.h:249
si
vnet_sw_interface_t * si
Definition: interface_output.c:418
vec_foreach
#define vec_foreach(var, vec)
Vector iterator.
Definition: vec_bootstrap.h:213
snort_qpair_t::deq_ring
volatile u32 * deq_ring
Definition: snort.h:21
n_left
u32 n_left
Definition: interface_output.c:1096
SNORT_ENQ_NEXT_DROP
@ SNORT_ENQ_NEXT_DROP
Definition: snort.h:89
snort_deq_error_strings
static char * snort_deq_error_strings[]
Definition: dequeue.c:40
snort_deq_node_interrupt
static u32 snort_deq_node_interrupt(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: dequeue.c:177
snort_qpair_t::ready
u32 ready
Definition: snort.h:28
vlib_main_t
Definition: main.h:102
vlib_node_t
Definition: node.h:247
b
vlib_buffer_t ** b
Definition: nat44_ei_out2in.c:717
snort_qpair_t::next_desc
u32 next_desc
Definition: snort.h:22
u8
unsigned char u8
Definition: types.h:56
snort_qpair_t::deq_head
volatile u32 * deq_head
Definition: snort.h:19
snort_deq_instance
static_always_inline uword snort_deq_instance(vlib_main_t *vm, u32 instance_index, snort_qpair_t *qp, u32 *buffer_indices, u16 *nexts, u32 max_recv)
Definition: dequeue.c:47
format_snort_deq_trace
static u8 * format_snort_deq_trace(u8 *s, va_list *args)
Definition: dequeue.c:16
snort_deq_instance_poll
static_always_inline uword snort_deq_instance_poll(vlib_main_t *vm, snort_qpair_t *qp, u32 *buffer_indices, u16 *nexts, u32 max_recv)
Definition: dequeue.c:220
snort_process_all_buffer_indices
static_always_inline u32 snort_process_all_buffer_indices(snort_qpair_t *qp, u32 *b, u16 *nexts, u32 max_recv, u8 drop_on_disconnect)
Definition: dequeue.c:117
nexts
u16 nexts[VLIB_FRAME_SIZE]
Definition: nat44_ei_out2in.c:718
vlib_node_runtime_t
Definition: node.h:454
snort_qpair_t::log2_queue_size
u8 log2_queue_size
Definition: snort.h:16
DAQ_VPP_ACTION_FORWARD
@ DAQ_VPP_ACTION_FORWARD
Definition: daq_vpp.h:65
snort_main
snort_main_t snort_main
Definition: main.c:12
type
vl_api_fib_path_type_t type
Definition: fib_types.api:123
VLIB_REGISTER_NODE
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169