Line data Source code
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 : {
11 : u32 next_index;
12 : u32 sw_if_index;
13 : u16 instance;
14 : u16 qpair;
15 : u32 enq_slot;
16 : u32 desc_index;
17 : daq_vpp_desc_t desc;
18 : } snort_enq_trace_t;
19 :
20 : static u8 *
21 0 : format_snort_enq_trace (u8 *s, va_list *args)
22 : {
23 0 : CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
24 0 : CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
25 0 : snort_enq_trace_t *t = va_arg (*args, snort_enq_trace_t *);
26 0 : u32 indent = format_get_indent (s);
27 :
28 0 : 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",
32 : t->sw_if_index, t->next_index, format_white_space, indent,
33 0 : t->instance, t->qpair, t->desc_index, t->enq_slot,
34 0 : format_white_space, indent, t->desc.buffer_pool, t->desc.offset,
35 0 : t->desc.length, t->desc.address_space_id);
36 :
37 0 : 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,
48 : foreach_snort_enq_error
49 : #undef _
50 : SNORT_ENQ_N_ERROR,
51 : } snort_enq_error_t;
52 :
53 : static char *snort_enq_error_strings[] = {
54 : #define _(sym, string) string,
55 : foreach_snort_enq_error
56 : #undef _
57 : };
58 :
59 : static_always_inline uword
60 0 : snort_enq_node_inline (vlib_main_t *vm, vlib_node_runtime_t *node,
61 : vlib_frame_t *frame, int with_trace)
62 : {
63 0 : snort_main_t *sm = &snort_main;
64 0 : snort_instance_t *si = 0;
65 0 : snort_qpair_t *qp = 0;
66 0 : u32 thread_index = vm->thread_index;
67 0 : u32 n_left = frame->n_vectors;
68 0 : u32 n_trace = 0;
69 0 : u32 total_enq = 0, n_processed = 0;
70 0 : u32 *from = vlib_frame_vector_args (frame);
71 0 : vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b = bufs;
72 0 : u16 nexts[VLIB_FRAME_SIZE], *next = nexts;
73 :
74 0 : vlib_get_buffers (vm, from, bufs, n_left);
75 :
76 0 : while (n_left)
77 : {
78 : u64 fa_data;
79 : u32 instance_index, next_index, n;
80 : u32 l3_offset;
81 :
82 0 : fa_data =
83 0 : *(u64 *) vnet_feature_next_with_data (&next_index, b[0], sizeof (u64));
84 :
85 0 : instance_index = (u32) (fa_data & 0xffffffff);
86 0 : l3_offset =
87 0 : (fa_data >> 32) ? vnet_buffer (b[0])->ip.save_rewrite_length : 0;
88 0 : si = vec_elt_at_index (sm->instances, instance_index);
89 :
90 : /* if client isn't connected skip enqueue and take default action */
91 0 : if (PREDICT_FALSE (si->client_index == ~0))
92 : {
93 0 : if (si->drop_on_disconnect)
94 0 : next[0] = SNORT_ENQ_NEXT_DROP;
95 : else
96 0 : next[0] = next_index;
97 0 : next++;
98 0 : n_processed++;
99 : }
100 : else
101 : {
102 0 : qp = vec_elt_at_index (si->qpairs, thread_index);
103 0 : n = qp->n_pending++;
104 0 : daq_vpp_desc_t *d = qp->pending_descs + n;
105 :
106 0 : qp->pending_nexts[n] = next_index;
107 0 : qp->pending_buffers[n] = from[0];
108 :
109 0 : vlib_buffer_chain_linearize (vm, b[0]);
110 :
111 : /* If this pkt is traced, snapshoot the data */
112 0 : if (with_trace && b[0]->flags & VLIB_BUFFER_IS_TRACED)
113 0 : n_trace++;
114 :
115 : /* fill descriptor */
116 0 : d->buffer_pool = b[0]->buffer_pool_index;
117 0 : d->length = b[0]->current_length;
118 0 : d->offset = (u8 *) b[0]->data + b[0]->current_data + l3_offset -
119 0 : sm->buffer_pool_base_addrs[d->buffer_pool];
120 0 : d->address_space_id = vnet_buffer (b[0])->sw_if_index[VLIB_RX];
121 : }
122 :
123 0 : n_left--;
124 0 : from++;
125 0 : b++;
126 : }
127 :
128 0 : if (n_processed)
129 : {
130 0 : vlib_node_increment_counter (vm, snort_enq_node.index,
131 : SNORT_ENQ_ERROR_NO_INSTANCE, n_processed);
132 0 : vlib_buffer_enqueue_to_next (vm, node, vlib_frame_vector_args (frame),
133 : nexts, n_processed);
134 : }
135 :
136 0 : vec_foreach (si, sm->instances)
137 : {
138 : u32 head, freelist_len, n_pending, n_enq, mask;
139 0 : u64 ctr = 1;
140 0 : qp = vec_elt_at_index (si->qpairs, thread_index);
141 0 : mask = pow2_mask (qp->log2_queue_size);
142 0 : n_pending = qp->n_pending;
143 0 : qp->n_pending = 0;
144 :
145 0 : if (n_pending == 0)
146 0 : continue;
147 :
148 0 : freelist_len = vec_len (qp->freelist);
149 :
150 0 : if (freelist_len < n_pending)
151 : {
152 0 : n_enq = freelist_len;
153 0 : vlib_buffer_free (vm, qp->pending_buffers + n_enq,
154 : n_pending - n_enq);
155 0 : vlib_node_increment_counter (vm, snort_enq_node.index,
156 : SNORT_ENQ_ERROR_NO_ENQ_SLOTS,
157 0 : n_pending - n_enq);
158 : }
159 : else
160 0 : n_enq = n_pending;
161 :
162 0 : if (n_enq == 0)
163 0 : continue;
164 :
165 0 : total_enq += n_enq;
166 0 : head = *qp->enq_head;
167 :
168 0 : for (u32 i = 0; i < n_enq; i++)
169 : {
170 0 : u32 desc_index = qp->freelist[--freelist_len];
171 0 : qp->next_indices[desc_index] = qp->pending_nexts[i];
172 0 : ASSERT (qp->buffer_indices[desc_index] == ~0);
173 0 : qp->buffer_indices[desc_index] = qp->pending_buffers[i];
174 0 : clib_memcpy_fast (qp->descriptors + desc_index,
175 0 : qp->pending_descs + i, sizeof (daq_vpp_desc_t));
176 0 : qp->enq_ring[head & mask] = desc_index;
177 :
178 : /* trace */
179 0 : if (with_trace && n_trace)
180 : {
181 0 : vlib_buffer_t *tb = vlib_get_buffer (vm, qp->pending_buffers[i]);
182 0 : if (tb->flags & VLIB_BUFFER_IS_TRACED)
183 : {
184 : snort_enq_trace_t *t =
185 0 : vlib_add_trace (vm, node, tb, sizeof (*t));
186 0 : t->sw_if_index = vnet_buffer (tb)->sw_if_index[VLIB_RX];
187 0 : t->next_index = qp->pending_nexts[i];
188 0 : t->instance = si->index;
189 0 : t->qpair = qp - si->qpairs;
190 0 : t->enq_slot = head & mask;
191 0 : t->desc_index = desc_index;
192 0 : clib_memcpy_fast (&t->desc, qp->pending_descs + i,
193 : sizeof (daq_vpp_desc_t));
194 : }
195 : }
196 0 : head = head + 1;
197 : }
198 :
199 0 : __atomic_store_n (qp->enq_head, head, __ATOMIC_RELEASE);
200 0 : vec_set_len (qp->freelist, freelist_len);
201 0 : if (sm->input_mode == VLIB_NODE_STATE_INTERRUPT)
202 : {
203 0 : if (write (qp->enq_fd, &ctr, sizeof (ctr)) < 0)
204 0 : vlib_node_increment_counter (vm, snort_enq_node.index,
205 : SNORT_ENQ_ERROR_SOCKET_ERROR, 1);
206 : }
207 : }
208 :
209 0 : return total_enq;
210 : }
211 :
212 2300 : VLIB_NODE_FN (snort_enq_node)
213 : (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
214 : {
215 0 : if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE))
216 0 : return snort_enq_node_inline (vm, node, frame, 1 /* is_trace*/);
217 : else
218 0 : return snort_enq_node_inline (vm, node, frame, 0 /* is_trace*/);
219 : }
220 :
221 43775 : VLIB_REGISTER_NODE (snort_enq_node) = {
222 : .name = "snort-enq",
223 : .vector_size = sizeof (u32),
224 : .format_trace = format_snort_enq_trace,
225 : .type = VLIB_NODE_TYPE_INTERNAL,
226 : .n_next_nodes = SNORT_ENQ_N_NEXT_NODES,
227 : .next_nodes = SNORT_ENQ_NEXT_NODES,
228 : .n_errors = ARRAY_LEN (snort_enq_error_strings),
229 : .error_strings = snort_enq_error_strings,
230 : };
|