FD.io VPP  v21.10.1-2-g0a485f517
Vector Packet Processing
enqueue.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 {
19 
20 static u8 *
21 format_snort_enq_trace (u8 *s, va_list *args)
22 {
23  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
24  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
25  snort_enq_trace_t *t = va_arg (*args, snort_enq_trace_t *);
26  u32 indent = format_get_indent (s);
27 
28  s = format (s,
29  "sw-if-index %u next-index %u\n"
30  "%Uinstance %u qpair %u desc-index %u slot %u\n"
31  "%Udesc: buffer-pool %u offset %u len %u address-space-id %u\n",
33  t->instance, t->qpair, t->desc_index, t->enq_slot,
36 
37  return s;
38 }
39 
40 #define foreach_snort_enq_error \
41  _ (SOCKET_ERROR, "write socket error") \
42  _ (NO_INSTANCE, "no snort instance") \
43  _ (NO_ENQ_SLOTS, "no enqueue slots (packet dropped)")
44 
45 typedef enum
46 {
47 #define _(sym, str) SNORT_ENQ_ERROR_##sym,
49 #undef _
52 
53 static char *snort_enq_error_strings[] = {
54 #define _(sym, string) string,
56 #undef _
57 };
58 
61  vlib_frame_t *frame, int with_trace)
62 {
63  snort_main_t *sm = &snort_main;
64  snort_instance_t *si = 0;
65  snort_qpair_t *qp = 0;
67  u32 n_left = frame->n_vectors;
68  u32 n_trace = 0;
69  u32 total_enq = 0, n_processed = 0;
73 
75 
76  while (n_left)
77  {
78  u32 instance_index, next_index, n;
79  instance_index =
80  *(u32 *) vnet_feature_next_with_data (&next_index, b[0], sizeof (u32));
81  si = vec_elt_at_index (sm->instances, instance_index);
82 
83  /* if client isn't connected skip enqueue and take default action */
84  if (PREDICT_FALSE (si->client_index == ~0))
85  {
86  if (si->drop_on_disconnect)
88  else
89  next[0] = next_index;
90  next++;
91  n_processed++;
92  }
93  else
94  {
95  qp = vec_elt_at_index (si->qpairs, thread_index);
96  n = qp->n_pending++;
97  daq_vpp_desc_t *d = qp->pending_descs + n;
98 
99  qp->pending_nexts[n] = next_index;
100  qp->pending_buffers[n] = from[0];
101 
103 
104  /* If this pkt is traced, snapshoot the data */
105  if (with_trace && b[0]->flags & VLIB_BUFFER_IS_TRACED)
106  n_trace++;
107 
108  /* fill descriptor */
110  d->length = b[0]->current_length;
111  d->offset = (u8 *) b[0]->data + b[0]->current_data -
113  d->address_space_id = vnet_buffer (b[0])->sw_if_index[VLIB_RX];
114  }
115 
116  n_left--;
117  from++;
118  b++;
119  }
120 
121  if (n_processed)
122  {
124  SNORT_ENQ_ERROR_NO_INSTANCE, n_processed);
126  nexts, n_processed);
127  }
128 
129  vec_foreach (si, sm->instances)
130  {
131  u32 head, freelist_len, n_pending, n_enq, mask;
132  u64 ctr = 1;
133  qp = vec_elt_at_index (si->qpairs, thread_index);
135  n_pending = qp->n_pending;
136  qp->n_pending = 0;
137 
138  if (n_pending == 0)
139  continue;
140 
141  freelist_len = vec_len (qp->freelist);
142 
143  if (freelist_len < n_pending)
144  {
145  n_enq = freelist_len;
146  vlib_buffer_free (vm, qp->pending_buffers + n_enq,
147  n_pending - n_enq);
149  SNORT_ENQ_ERROR_NO_ENQ_SLOTS,
150  n_pending - n_enq);
151  }
152  else
153  n_enq = n_pending;
154 
155  if (n_enq == 0)
156  continue;
157 
158  total_enq += n_enq;
159  head = *qp->enq_head;
160 
161  for (u32 i = 0; i < n_enq; i++)
162  {
163  u32 desc_index = qp->freelist[--freelist_len];
164  qp->next_indices[desc_index] = qp->pending_nexts[i];
165  ASSERT (qp->buffer_indices[desc_index] == ~0);
166  qp->buffer_indices[desc_index] = qp->pending_buffers[i];
167  clib_memcpy_fast (qp->descriptors + desc_index,
168  qp->pending_descs + i, sizeof (daq_vpp_desc_t));
169  qp->enq_ring[head & mask] = desc_index;
170 
171  /* trace */
172  if (with_trace && n_trace)
173  {
175  if (tb->flags & VLIB_BUFFER_IS_TRACED)
176  {
177  snort_enq_trace_t *t =
178  vlib_add_trace (vm, node, tb, sizeof (*t));
179  t->sw_if_index = vnet_buffer (tb)->sw_if_index[VLIB_RX];
180  t->next_index = qp->pending_nexts[i];
181  t->instance = si->index;
182  t->qpair = qp - si->qpairs;
183  t->enq_slot = head & mask;
184  t->desc_index = desc_index;
185  clib_memcpy_fast (&t->desc, qp->pending_descs + i,
186  sizeof (daq_vpp_desc_t));
187  }
188  }
189  head = head + 1;
190  }
191 
192  __atomic_store_n (qp->enq_head, head, __ATOMIC_RELEASE);
193  _vec_len (qp->freelist) = freelist_len;
194  if (sm->input_mode == VLIB_NODE_STATE_INTERRUPT)
195  {
196  if (write (qp->enq_fd, &ctr, sizeof (ctr)) < 0)
198  SNORT_ENQ_ERROR_SOCKET_ERROR, 1);
199  }
200  }
201 
202  return total_enq;
203 }
204 
207 {
208  if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE))
209  return snort_enq_node_inline (vm, node, frame, 1 /* is_trace*/);
210  else
211  return snort_enq_node_inline (vm, node, frame, 0 /* is_trace*/);
212 }
213 
215  .name = "snort-enq",
216  .vector_size = sizeof (u32),
217  .format_trace = format_snort_enq_trace,
219  .n_next_nodes = SNORT_ENQ_N_NEXT_NODES,
220  .next_nodes = SNORT_ENQ_NEXT_NODES,
221  .n_errors = ARRAY_LEN (snort_enq_error_strings),
222  .error_strings = snort_enq_error_strings,
223 };
vlib.h
vlib_buffer_free
static void vlib_buffer_free(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Free buffers Frees the entire buffer chain for each buffer.
Definition: buffer_funcs.h:979
vlib_buffer_t::buffer_pool_index
u8 buffer_pool_index
index of buffer pool this buffer belongs.
Definition: buffer.h:142
snort_qpair_t::freelist
u32 * freelist
Definition: snort.h:27
SNORT_ENQ_N_NEXT_NODES
@ SNORT_ENQ_N_NEXT_NODES
Definition: snort.h:90
frame
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: enqueue.c:207
thread_index
u32 thread_index
Definition: nat44_ei_hairpinning.c:495
bufs
vlib_buffer_t * bufs[VLIB_FRAME_SIZE]
Definition: nat44_ei_out2in.c:717
snort_enq_trace_t::sw_if_index
u32 sw_if_index
Definition: enqueue.c:12
snort_qpair_t::descriptors
daq_vpp_desc_t * descriptors
Definition: snort.h:17
next_index
nat44_ei_hairpin_src_next_t next_index
Definition: nat44_ei_hairpinning.c:412
format_snort_enq_trace
static u8 * format_snort_enq_trace(u8 *s, va_list *args)
Definition: enqueue.c:21
vlib_get_buffer
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:111
pow2_mask
static uword pow2_mask(uword x)
Definition: clib.h:252
snort_qpair_t::buffer_indices
u32 * buffer_indices
Definition: snort.h:25
snort_enq_node
vlib_node_registration_t snort_enq_node
(constructor) VLIB_REGISTER_NODE (snort_enq_node)
Definition: enqueue.c:214
vlib_get_buffers
vlib_get_buffers(vm, from, b, n_left_from)
next
u16 * next
Definition: nat44_ei_out2in.c:718
VLIB_NODE_TYPE_INTERNAL
@ VLIB_NODE_TYPE_INTERNAL
Definition: node.h:72
VLIB_FRAME_SIZE
#define VLIB_FRAME_SIZE
Definition: node.h:368
snort_enq_trace_t::desc
daq_vpp_desc_t desc
Definition: enqueue.c:17
u16
unsigned short u16
Definition: types.h:57
snort_enq_trace_t::enq_slot
u32 enq_slot
Definition: enqueue.c:15
VLIB_RX
@ VLIB_RX
Definition: defs.h:46
snort_enq_trace_t::next_index
u32 next_index
Definition: enqueue.c:11
snort.h
daq_vpp_desc_t
Definition: daq_vpp.h:68
daq_vpp_desc_t::length
uint16_t length
Definition: daq_vpp.h:71
vlib_buffer_enqueue_to_next
vlib_buffer_enqueue_to_next(vm, node, from,(u16 *) nexts, frame->n_vectors)
vnet_feature_next_with_data
static_always_inline void * vnet_feature_next_with_data(u32 *next0, vlib_buffer_t *b0, u32 n_data_bytes)
Definition: feature.h:309
snort_enq_trace_t::desc_index
u32 desc_index
Definition: enqueue.c:16
vlib_frame_t
Definition: node.h:372
clib_memcpy_fast
static_always_inline void * clib_memcpy_fast(void *restrict dst, const void *restrict src, size_t n)
Definition: string.h:92
snort_qpair_t::enq_ring
volatile u32 * enq_ring
Definition: snort.h:20
snort_qpair_t::enq_fd
int enq_fd
Definition: snort.h:23
daq_vpp_desc_t::offset
uint32_t offset
Definition: daq_vpp.h:70
snort_main_t
Definition: snort.h:70
vec_len
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
Definition: vec_bootstrap.h:142
snort_qpair_t::pending_buffers
u32 pending_buffers[VLIB_FRAME_SIZE]
Definition: snort.h:33
VLIB_NODE_FN
#define VLIB_NODE_FN(node)
Definition: node.h:202
feature.h
CLIB_UNUSED
#define CLIB_UNUSED(x)
Definition: clib.h:90
vnet_buffer
#define vnet_buffer(b)
Definition: buffer.h:441
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
snort_enq_node_inline
static_always_inline uword snort_enq_node_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, int with_trace)
Definition: enqueue.c:60
VLIB_NODE_FLAG_TRACE
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:291
snort_enq_trace_t::qpair
u16 qpair
Definition: enqueue.c:14
PREDICT_FALSE
#define PREDICT_FALSE(x)
Definition: clib.h:124
ARRAY_LEN
#define ARRAY_LEN(x)
Definition: clib.h:70
vlib_frame_vector_args
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:301
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
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
mask
vl_api_pnat_mask_t mask
Definition: pnat.api:45
daq_vpp_desc_t::buffer_pool
uint8_t buffer_pool
Definition: daq_vpp.h:73
SNORT_ENQ_NEXT_NODES
#define SNORT_ENQ_NEXT_NODES
Definition: snort.h:93
snort_qpair_t::enq_head
volatile u32 * enq_head
Definition: snort.h:18
vlib_buffer_chain_linearize
static u32 vlib_buffer_chain_linearize(vlib_main_t *vm, vlib_buffer_t *b)
Definition: buffer_funcs.h:1471
vlib_node_registration_t
struct _vlib_node_registration vlib_node_registration_t
node
vlib_main_t vlib_node_runtime_t * node
Definition: enqueue.c:206
vlib_buffer_t::current_length
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:122
data
u8 data[128]
Definition: ipsec_types.api:95
snort_main_t::input_mode
u32 input_mode
Definition: snort.h:79
snort_qpair_t::next_indices
u16 * next_indices
Definition: snort.h:26
foreach_snort_enq_error
#define foreach_snort_enq_error
Definition: enqueue.c:40
snort_qpair_t::pending_descs
daq_vpp_desc_t pending_descs[VLIB_FRAME_SIZE]
Definition: snort.h:34
snort_enq_error_t
snort_enq_error_t
Definition: enqueue.c:45
snort_instance_t
Definition: snort.h:37
u64
unsigned long u64
Definition: types.h:89
format
description fragment has unexpected format
Definition: map.api:433
ASSERT
#define ASSERT(truth)
Definition: error_bootstrap.h:69
snort_qpair_t
Definition: snort.h:13
format_get_indent
static u32 format_get_indent(u8 *s)
Definition: format.h:72
snort_qpair_t::pending_nexts
u16 pending_nexts[VLIB_FRAME_SIZE]
Definition: snort.h:32
u32
unsigned int u32
Definition: types.h:88
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
daq_vpp_desc_t::address_space_id
uint16_t address_space_id
Definition: daq_vpp.h:72
n_left
u32 n_left
Definition: interface_output.c:1096
SNORT_ENQ_NEXT_DROP
@ SNORT_ENQ_NEXT_DROP
Definition: snort.h:89
snort_enq_trace_t
Definition: enqueue.c:9
SNORT_ENQ_N_ERROR
@ SNORT_ENQ_N_ERROR
Definition: enqueue.c:50
snort_qpair_t::n_pending
u32 n_pending
Definition: snort.h:31
vm
vlib_main_t * vm
Definition: enqueue.c:206
vlib_main_t
Definition: main.h:102
vlib_node_t
Definition: node.h:247
vlib_add_trace
void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace.c:628
b
vlib_buffer_t ** b
Definition: nat44_ei_out2in.c:717
u8
unsigned char u8
Definition: types.h:56
i
int i
Definition: flowhash_template.h:376
nexts
u16 nexts[VLIB_FRAME_SIZE]
Definition: nat44_ei_out2in.c:718
snort_enq_error_strings
static char * snort_enq_error_strings[]
Definition: enqueue.c:53
snort_main_t::buffer_pool_base_addrs
u8 ** buffer_pool_base_addrs
Definition: snort.h:77
vlib_node_runtime_t
Definition: node.h:454
snort_enq_trace_t::instance
u16 instance
Definition: enqueue.c:13
snort_qpair_t::log2_queue_size
u8 log2_queue_size
Definition: snort.h:16
from
from
Definition: nat44_ei_hairpinning.c:415
snort_main
snort_main_t snort_main
Definition: main.c:12
type
vl_api_fib_path_type_t type
Definition: fib_types.api:123
format_white_space
u8 * format_white_space(u8 *s, va_list *va)
Definition: std-formats.c:129
vlib_buffer_t::flags
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index,...
Definition: buffer.h:133
vlib_buffer_t
VLIB buffer representation.
Definition: buffer.h:111
VLIB_REGISTER_NODE
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
flags
vl_api_wireguard_peer_flags_t flags
Definition: wireguard.api:105