LCOV - code coverage report
Current view: top level - plugins/snort - enqueue.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 2 104 1.9 %
Date: 2023-10-26 01:39:38 Functions: 6 12 50.0 %

          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             : };

Generated by: LCOV version 1.14