LCOV - code coverage report
Current view: top level - vnet/lawful-intercept - node.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 2 64 3.1 %
Date: 2023-10-26 01:39:38 Functions: 6 11 54.5 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2015 Cisco and/or its affiliates.
       3             :  * Licensed under the Apache License, Version 2.0 (the "License");
       4             :  * you may not use this file except in compliance with the License.
       5             :  * You may obtain a copy of the License at:
       6             :  *
       7             :  *     http://www.apache.org/licenses/LICENSE-2.0
       8             :  *
       9             :  * Unless required by applicable law or agreed to in writing, software
      10             :  * distributed under the License is distributed on an "AS IS" BASIS,
      11             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12             :  * See the License for the specific language governing permissions and
      13             :  * limitations under the License.
      14             :  */
      15             : 
      16             : #include <vlib/vlib.h>
      17             : #include <vnet/vnet.h>
      18             : #include <vppinfra/error.h>
      19             : 
      20             : #include <vnet/lawful-intercept/lawful_intercept.h>
      21             : 
      22             : #include <vppinfra/error.h>
      23             : #include <vppinfra/elog.h>
      24             : 
      25             : extern vlib_node_registration_t li_hit_node;
      26             : 
      27             : typedef struct
      28             : {
      29             :   u32 next_index;
      30             : } li_hit_trace_t;
      31             : 
      32             : /* packet trace format function */
      33             : static u8 *
      34           0 : format_li_hit_trace (u8 * s, va_list * args)
      35             : {
      36           0 :   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
      37           0 :   CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
      38           0 :   li_hit_trace_t *t = va_arg (*args, li_hit_trace_t *);
      39             : 
      40           0 :   s = format (s, "LI_HIT: next index %d", t->next_index);
      41             : 
      42           0 :   return s;
      43             : }
      44             : 
      45             : #define foreach_li_hit_error                                    \
      46             : _(HITS, "LI packets processed")                                 \
      47             : _(NO_COLLECTOR, "No collector configured")                      \
      48             : _(BUFFER_ALLOCATION_FAILURE, "Buffer allocation failure")
      49             : 
      50             : typedef enum
      51             : {
      52             : #define _(sym,str) LI_HIT_ERROR_##sym,
      53             :   foreach_li_hit_error
      54             : #undef _
      55             :     LI_HIT_N_ERROR,
      56             : } li_hit_error_t;
      57             : 
      58             : static char *li_hit_error_strings[] = {
      59             : #define _(sym,string) string,
      60             :   foreach_li_hit_error
      61             : #undef _
      62             : };
      63             : 
      64             : typedef enum
      65             : {
      66             :   LI_HIT_NEXT_ETHERNET,
      67             :   LI_HIT_N_NEXT,
      68             : } li_hit_next_t;
      69             : 
      70        2300 : VLIB_NODE_FN (li_hit_node) (vlib_main_t * vm,
      71             :                             vlib_node_runtime_t * node, vlib_frame_t * frame)
      72             : {
      73             :   u32 n_left_from, *from, *to_next;
      74             :   li_hit_next_t next_index;
      75           0 :   vlib_frame_t *int_frame = 0;
      76           0 :   u32 *to_int_next = 0;
      77           0 :   li_main_t *lm = &li_main;
      78             : 
      79           0 :   from = vlib_frame_vector_args (frame);
      80           0 :   n_left_from = frame->n_vectors;
      81           0 :   next_index = node->cached_next_index;
      82             : 
      83           0 :   if (PREDICT_FALSE (vec_len (lm->collectors) == 0))
      84             :     {
      85           0 :       vlib_node_increment_counter (vm, li_hit_node.index,
      86             :                                    LI_HIT_ERROR_NO_COLLECTOR, n_left_from);
      87             :     }
      88             :   else
      89             :     {
      90             :       /* The intercept frame... */
      91           0 :       int_frame = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
      92           0 :       to_int_next = vlib_frame_vector_args (int_frame);
      93             :     }
      94             : 
      95           0 :   while (n_left_from > 0)
      96             :     {
      97             :       u32 n_left_to_next;
      98             : 
      99           0 :       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
     100             : 
     101             : #if 0
     102             :       while (n_left_from >= 4 && n_left_to_next >= 2)
     103             :         {
     104             :           u32 next0 = LI_HIT_NEXT_INTERFACE_OUTPUT;
     105             :           u32 next1 = LI_HIT_NEXT_INTERFACE_OUTPUT;
     106             :           u32 sw_if_index0, sw_if_index1;
     107             :           u8 tmp0[6], tmp1[6];
     108             :           ethernet_header_t *en0, *en1;
     109             :           u32 bi0, bi1;
     110             :           vlib_buffer_t *b0, *b1;
     111             : 
     112             :           /* Prefetch next iteration. */
     113             :           {
     114             :             vlib_buffer_t *p2, *p3;
     115             : 
     116             :             p2 = vlib_get_buffer (vm, from[2]);
     117             :             p3 = vlib_get_buffer (vm, from[3]);
     118             : 
     119             :             vlib_prefetch_buffer_header (p2, LOAD);
     120             :             vlib_prefetch_buffer_header (p3, LOAD);
     121             : 
     122             :             clib_prefetch_store (p2->data);
     123             :             clib_prefetch_store (p3->data);
     124             :           }
     125             : 
     126             :           /* speculatively enqueue b0 and b1 to the current next frame */
     127             :           to_next[0] = bi0 = from[0];
     128             :           to_next[1] = bi1 = from[1];
     129             :           from += 2;
     130             :           to_next += 2;
     131             :           n_left_from -= 2;
     132             :           n_left_to_next -= 2;
     133             : 
     134             :           b0 = vlib_get_buffer (vm, bi0);
     135             :           b1 = vlib_get_buffer (vm, bi1);
     136             : 
     137             :           /* $$$$$ Dual loop: process 2 x packets here $$$$$ */
     138             :           ASSERT (b0->current_data == 0);
     139             :           ASSERT (b1->current_data == 0);
     140             : 
     141             :           en0 = vlib_buffer_get_current (b0);
     142             :           en1 = vlib_buffer_get_current (b1);
     143             : 
     144             :           sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
     145             :           sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
     146             : 
     147             :           /* Send pkt back out the RX interface */
     148             :           vnet_buffer (b0)->sw_if_index[VLIB_TX] = sw_if_index0;
     149             :           vnet_buffer (b1)->sw_if_index[VLIB_TX] = sw_if_index1;
     150             : 
     151             :           /* $$$$$ End of processing 2 x packets $$$$$ */
     152             : 
     153             :           if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)))
     154             :             {
     155             :               if (b0->flags & VLIB_BUFFER_IS_TRACED)
     156             :                 {
     157             :                   li_hit_trace_t *t =
     158             :                     vlib_add_trace (vm, node, b0, sizeof (*t));
     159             :                   t->sw_if_index = sw_if_index0;
     160             :                   t->next_index = next0;
     161             :                 }
     162             :               if (b1->flags & VLIB_BUFFER_IS_TRACED)
     163             :                 {
     164             :                   li_hit_trace_t *t =
     165             :                     vlib_add_trace (vm, node, b1, sizeof (*t));
     166             :                   t->sw_if_index = sw_if_index1;
     167             :                   t->next_index = next1;
     168             :                 }
     169             :             }
     170             : 
     171             :           /* verify speculative enqueues, maybe switch current next frame */
     172             :           vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
     173             :                                            to_next, n_left_to_next,
     174             :                                            bi0, bi1, next0, next1);
     175             :         }
     176             : #endif /* $$$ dual-loop off */
     177             : 
     178           0 :       while (n_left_from > 0 && n_left_to_next > 0)
     179             :         {
     180             :           u32 bi0;
     181             :           vlib_buffer_t *b0;
     182             :           vlib_buffer_t *c0;
     183             :           ip4_udp_header_t *iu0;
     184             :           ip4_header_t *ip0;
     185             :           udp_header_t *udp0;
     186           0 :           u32 next0 = LI_HIT_NEXT_ETHERNET;
     187             : 
     188             :           /* speculatively enqueue b0 to the current next frame */
     189           0 :           bi0 = from[0];
     190           0 :           to_next[0] = bi0;
     191           0 :           from += 1;
     192           0 :           to_next += 1;
     193           0 :           n_left_from -= 1;
     194           0 :           n_left_to_next -= 1;
     195             : 
     196           0 :           b0 = vlib_get_buffer (vm, bi0);
     197           0 :           if (PREDICT_TRUE (to_int_next != 0))
     198             :             {
     199             :               /* Make an intercept copy. This can fail. */
     200           0 :               c0 = vlib_buffer_copy (vm, b0);
     201             : 
     202           0 :               if (PREDICT_FALSE (c0 == 0))
     203             :                 {
     204           0 :                   vlib_node_increment_counter
     205             :                     (vm, node->node_index,
     206             :                      LI_HIT_ERROR_BUFFER_ALLOCATION_FAILURE, 1);
     207           0 :                   goto skip;
     208             :                 }
     209             : 
     210           0 :               vlib_buffer_advance (c0, -sizeof (*iu0));
     211             : 
     212           0 :               iu0 = vlib_buffer_get_current (c0);
     213           0 :               ip0 = &iu0->ip4;
     214             : 
     215           0 :               ip0->ip_version_and_header_length = 0x45;
     216           0 :               ip0->ttl = 254;
     217           0 :               ip0->protocol = IP_PROTOCOL_UDP;
     218             : 
     219           0 :               ip0->src_address.as_u32 = lm->src_addrs[0].as_u32;
     220           0 :               ip0->dst_address.as_u32 = lm->collectors[0].as_u32;
     221           0 :               ip0->length = vlib_buffer_length_in_chain (vm, c0);
     222           0 :               ip0->checksum = ip4_header_checksum (ip0);
     223             : 
     224           0 :               udp0 = &iu0->udp;
     225           0 :               udp0->src_port = udp0->dst_port =
     226           0 :                 clib_host_to_net_u16 (lm->ports[0]);
     227           0 :               udp0->checksum = 0;
     228           0 :               udp0->length =
     229           0 :                 clib_net_to_host_u16 (vlib_buffer_length_in_chain (vm, b0));
     230             : 
     231           0 :               to_int_next[0] = vlib_get_buffer_index (vm, c0);
     232           0 :               to_int_next++;
     233             :             }
     234             : 
     235           0 :         skip:
     236           0 :           if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)
     237             :                              && (b0->flags & VLIB_BUFFER_IS_TRACED)))
     238             :             {
     239           0 :               li_hit_trace_t *t = vlib_add_trace (vm, node, b0, sizeof (*t));
     240           0 :               t->next_index = next0;
     241             :             }
     242             : 
     243             :           /* verify speculative enqueue, maybe switch current next frame */
     244           0 :           vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
     245             :                                            to_next, n_left_to_next,
     246             :                                            bi0, next0);
     247             :         }
     248             : 
     249           0 :       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
     250             :     }
     251             : 
     252           0 :   if (int_frame)
     253             :     {
     254           0 :       int_frame->n_vectors = frame->n_vectors;
     255           0 :       vlib_put_frame_to_node (vm, ip4_lookup_node.index, int_frame);
     256             :     }
     257             : 
     258           0 :   vlib_node_increment_counter (vm, li_hit_node.index,
     259           0 :                                LI_HIT_ERROR_HITS, frame->n_vectors);
     260           0 :   return frame->n_vectors;
     261             : }
     262             : 
     263             : /* *INDENT-OFF* */
     264      183788 : VLIB_REGISTER_NODE (li_hit_node) = {
     265             :   .name = "li-hit",
     266             :   .vector_size = sizeof (u32),
     267             :   .format_trace = format_li_hit_trace,
     268             :   .type = VLIB_NODE_TYPE_INTERNAL,
     269             : 
     270             :   .n_errors = ARRAY_LEN(li_hit_error_strings),
     271             :   .error_strings = li_hit_error_strings,
     272             : 
     273             :   .n_next_nodes = LI_HIT_N_NEXT,
     274             : 
     275             :   /* edit / add dispositions here */
     276             :   .next_nodes = {
     277             :         [LI_HIT_NEXT_ETHERNET] = "ethernet-input-not-l2",
     278             :   },
     279             : };
     280             : /* *INDENT-ON* */
     281             : 
     282             : /*
     283             :  * fd.io coding-style-patch-verification: ON
     284             :  *
     285             :  * Local Variables:
     286             :  * eval: (c-set-style "gnu")
     287             :  * End:
     288             :  */

Generated by: LCOV version 1.14