LCOV - code coverage report
Current view: top level - vnet/ppp - node.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 41 139 29.5 %
Date: 2023-07-05 22:20:52 Functions: 10 12 83.3 %

          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             :  * ppp_node.c: ppp packet processing
      17             :  *
      18             :  * Copyright (c) 2010 Eliot Dresselhaus
      19             :  *
      20             :  * Permission is hereby granted, free of charge, to any person obtaining
      21             :  * a copy of this software and associated documentation files (the
      22             :  * "Software"), to deal in the Software without restriction, including
      23             :  * without limitation the rights to use, copy, modify, merge, publish,
      24             :  * distribute, sublicense, and/or sell copies of the Software, and to
      25             :  * permit persons to whom the Software is furnished to do so, subject to
      26             :  * the following conditions:
      27             :  *
      28             :  * The above copyright notice and this permission notice shall be
      29             :  * included in all copies or substantial portions of the Software.
      30             :  *
      31             :  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
      32             :  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
      33             :  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
      34             :  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
      35             :  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
      36             :  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
      37             :  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      38             :  */
      39             : 
      40             : #include <vlib/vlib.h>
      41             : #include <vnet/pg/pg.h>
      42             : #include <vnet/ppp/ppp.h>
      43             : #include <vppinfra/sparse_vec.h>
      44             : 
      45             : #define foreach_ppp_input_next                  \
      46             :   _ (PUNT, "error-punt")                      \
      47             :   _ (DROP, "error-drop")
      48             : 
      49             : typedef enum
      50             : {
      51             : #define _(s,n) PPP_INPUT_NEXT_##s,
      52             :   foreach_ppp_input_next
      53             : #undef _
      54             :     PPP_INPUT_N_NEXT,
      55             : } ppp_input_next_t;
      56             : 
      57             : typedef struct
      58             : {
      59             :   u8 packet_data[32];
      60             : } ppp_input_trace_t;
      61             : 
      62             : static u8 *
      63           0 : format_ppp_input_trace (u8 * s, va_list * va)
      64             : {
      65           0 :   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *);
      66           0 :   CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *);
      67           0 :   ppp_input_trace_t *t = va_arg (*va, ppp_input_trace_t *);
      68             : 
      69           0 :   s = format (s, "%U", format_ppp_header, t->packet_data);
      70             : 
      71           0 :   return s;
      72             : }
      73             : 
      74             : typedef struct
      75             : {
      76             :   /* Sparse vector mapping ppp protocol in network byte order
      77             :      to next index. */
      78             :   u16 *next_by_protocol;
      79             : 
      80             :   u32 *sparse_index_by_next_index;
      81             : } ppp_input_runtime_t;
      82             : 
      83             : static uword
      84           0 : ppp_input (vlib_main_t * vm,
      85             :            vlib_node_runtime_t * node, vlib_frame_t * from_frame)
      86             : {
      87           0 :   ppp_input_runtime_t *rt = (void *) node->runtime_data;
      88             :   u32 n_left_from, next_index, i_next, *from, *to_next;
      89             : 
      90           0 :   from = vlib_frame_vector_args (from_frame);
      91           0 :   n_left_from = from_frame->n_vectors;
      92             : 
      93           0 :   if (node->flags & VLIB_NODE_FLAG_TRACE)
      94           0 :     vlib_trace_frame_buffers_only (vm, node,
      95             :                                    from,
      96             :                                    n_left_from,
      97             :                                    sizeof (from[0]),
      98             :                                    sizeof (ppp_input_trace_t));
      99             : 
     100           0 :   next_index = node->cached_next_index;
     101           0 :   i_next = vec_elt (rt->sparse_index_by_next_index, next_index);
     102             : 
     103           0 :   while (n_left_from > 0)
     104             :     {
     105             :       u32 n_left_to_next;
     106             : 
     107           0 :       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
     108             : 
     109           0 :       while (n_left_from >= 4 && n_left_to_next >= 2)
     110             :         {
     111             :           u32 bi0, bi1;
     112             :           vlib_buffer_t *b0, *b1;
     113             :           ppp_header_t *h0, *h1;
     114             :           u32 i0, i1, protocol0, protocol1, enqueue_code;
     115             : 
     116             :           /* Prefetch next iteration. */
     117             :           {
     118             :             vlib_buffer_t *p2, *p3;
     119             : 
     120           0 :             p2 = vlib_get_buffer (vm, from[2]);
     121           0 :             p3 = vlib_get_buffer (vm, from[3]);
     122             : 
     123           0 :             vlib_prefetch_buffer_header (p2, LOAD);
     124           0 :             vlib_prefetch_buffer_header (p3, LOAD);
     125             : 
     126           0 :             CLIB_PREFETCH (p2->data, sizeof (h0[0]), LOAD);
     127           0 :             CLIB_PREFETCH (p3->data, sizeof (h1[0]), LOAD);
     128             :           }
     129             : 
     130           0 :           bi0 = from[0];
     131           0 :           bi1 = from[1];
     132           0 :           to_next[0] = bi0;
     133           0 :           to_next[1] = bi1;
     134           0 :           from += 2;
     135           0 :           to_next += 2;
     136           0 :           n_left_to_next -= 2;
     137           0 :           n_left_from -= 2;
     138             : 
     139           0 :           b0 = vlib_get_buffer (vm, bi0);
     140           0 :           b1 = vlib_get_buffer (vm, bi1);
     141             : 
     142           0 :           h0 = vlib_buffer_get_current (b0);
     143           0 :           h1 = vlib_buffer_get_current (b1);
     144             : 
     145           0 :           vlib_buffer_advance (b0, sizeof (ppp_header_t));
     146           0 :           vlib_buffer_advance (b1, sizeof (ppp_header_t));
     147             : 
     148             :           /* Index sparse array with network byte order. */
     149           0 :           protocol0 = h0->protocol;
     150           0 :           protocol1 = h1->protocol;
     151           0 :           sparse_vec_index2 (rt->next_by_protocol, protocol0, protocol1, &i0,
     152             :                              &i1);
     153             : 
     154           0 :           b0->error =
     155           0 :             node->errors[i0 ==
     156             :                          SPARSE_VEC_INVALID_INDEX ? PPP_ERROR_UNKNOWN_PROTOCOL
     157             :                          : PPP_ERROR_NONE];
     158           0 :           b1->error =
     159           0 :             node->errors[i1 ==
     160             :                          SPARSE_VEC_INVALID_INDEX ? PPP_ERROR_UNKNOWN_PROTOCOL
     161             :                          : PPP_ERROR_NONE];
     162             : 
     163           0 :           enqueue_code = (i0 != i_next) + 2 * (i1 != i_next);
     164             : 
     165           0 :           if (PREDICT_FALSE (enqueue_code != 0))
     166             :             {
     167           0 :               switch (enqueue_code)
     168             :                 {
     169           0 :                 case 1:
     170             :                   /* A B A */
     171           0 :                   to_next[-2] = bi1;
     172           0 :                   to_next -= 1;
     173           0 :                   n_left_to_next += 1;
     174           0 :                   vlib_set_next_frame_buffer (vm, node,
     175           0 :                                               vec_elt (rt->next_by_protocol,
     176             :                                                        i0), bi0);
     177           0 :                   break;
     178             : 
     179           0 :                 case 2:
     180             :                   /* A A B */
     181           0 :                   to_next -= 1;
     182           0 :                   n_left_to_next += 1;
     183           0 :                   vlib_set_next_frame_buffer (vm, node,
     184           0 :                                               vec_elt (rt->next_by_protocol,
     185             :                                                        i1), bi1);
     186           0 :                   break;
     187             : 
     188           0 :                 case 3:
     189             :                   /* A B B or A B C */
     190           0 :                   to_next -= 2;
     191           0 :                   n_left_to_next += 2;
     192           0 :                   vlib_set_next_frame_buffer (vm, node,
     193           0 :                                               vec_elt (rt->next_by_protocol,
     194             :                                                        i0), bi0);
     195           0 :                   vlib_set_next_frame_buffer (vm, node,
     196           0 :                                               vec_elt (rt->next_by_protocol,
     197             :                                                        i1), bi1);
     198           0 :                   if (i0 == i1)
     199             :                     {
     200           0 :                       vlib_put_next_frame (vm, node, next_index,
     201             :                                            n_left_to_next);
     202           0 :                       i_next = i1;
     203           0 :                       next_index = vec_elt (rt->next_by_protocol, i_next);
     204           0 :                       vlib_get_next_frame (vm, node, next_index, to_next,
     205             :                                            n_left_to_next);
     206             :                     }
     207             :                 }
     208             :             }
     209             :         }
     210             : 
     211           0 :       while (n_left_from > 0 && n_left_to_next > 0)
     212             :         {
     213             :           u32 bi0;
     214             :           vlib_buffer_t *b0;
     215             :           ppp_header_t *h0;
     216             :           u32 i0, protocol0;
     217             : 
     218           0 :           bi0 = from[0];
     219           0 :           to_next[0] = bi0;
     220           0 :           from += 1;
     221           0 :           to_next += 1;
     222           0 :           n_left_from -= 1;
     223           0 :           n_left_to_next -= 1;
     224             : 
     225           0 :           b0 = vlib_get_buffer (vm, bi0);
     226             : 
     227           0 :           h0 = vlib_buffer_get_current (b0);
     228             : 
     229           0 :           vlib_buffer_advance (b0, sizeof (ppp_header_t));
     230             : 
     231           0 :           protocol0 = h0->protocol;
     232           0 :           i0 = sparse_vec_index (rt->next_by_protocol, protocol0);
     233             : 
     234           0 :           b0->error =
     235           0 :             node->errors[i0 ==
     236             :                          SPARSE_VEC_INVALID_INDEX ? PPP_ERROR_UNKNOWN_PROTOCOL
     237             :                          : PPP_ERROR_NONE];
     238             : 
     239             :           /* Sent packet to wrong next? */
     240           0 :           if (PREDICT_FALSE (i0 != i_next))
     241             :             {
     242             :               /* Return old frame; remove incorrectly enqueued packet. */
     243           0 :               vlib_put_next_frame (vm, node, next_index, n_left_to_next + 1);
     244             : 
     245             :               /* Send to correct next. */
     246           0 :               i_next = i0;
     247           0 :               next_index = vec_elt (rt->next_by_protocol, i_next);
     248           0 :               vlib_get_next_frame (vm, node, next_index,
     249             :                                    to_next, n_left_to_next);
     250           0 :               to_next[0] = bi0;
     251           0 :               to_next += 1;
     252           0 :               n_left_to_next -= 1;
     253             :             }
     254             :         }
     255             : 
     256           0 :       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
     257             :     }
     258             : 
     259           0 :   return from_frame->n_vectors;
     260             : }
     261             : 
     262             : static char *ppp_error_strings[] = {
     263             : #define ppp_error(n,s) s,
     264             : #include "error.def"
     265             : #undef ppp_error
     266             : };
     267             : 
     268             : /* *INDENT-OFF* */
     269      178120 : VLIB_REGISTER_NODE (ppp_input_node) = {
     270             :   .function = ppp_input,
     271             :   .name = "ppp-input",
     272             :   /* Takes a vector of packets. */
     273             :   .vector_size = sizeof (u32),
     274             : 
     275             :   .runtime_data_bytes = sizeof (ppp_input_runtime_t),
     276             : 
     277             :   .n_errors = PPP_N_ERROR,
     278             :   .error_strings = ppp_error_strings,
     279             : 
     280             :   .n_next_nodes = PPP_INPUT_N_NEXT,
     281             :   .next_nodes = {
     282             : #define _(s,n) [PPP_INPUT_NEXT_##s] = n,
     283             :     foreach_ppp_input_next
     284             : #undef _
     285             :   },
     286             : 
     287             :   .format_buffer = format_ppp_header_with_length,
     288             :   .format_trace = format_ppp_input_trace,
     289             :   .unformat_buffer = unformat_ppp_header,
     290             : };
     291             : /* *INDENT-ON* */
     292             : 
     293             : static clib_error_t *
     294         612 : ppp_input_runtime_init (vlib_main_t * vm)
     295             : {
     296             :   ppp_input_runtime_t *rt;
     297             : 
     298         612 :   rt = vlib_node_get_runtime_data (vm, ppp_input_node.index);
     299             : 
     300         613 :   rt->next_by_protocol = sparse_vec_new
     301             :     ( /* elt bytes */ sizeof (rt->next_by_protocol[0]),
     302             :      /* bits in index */ BITS (((ppp_header_t *) 0)->protocol));
     303             : 
     304         613 :   vec_validate (rt->sparse_index_by_next_index, PPP_INPUT_NEXT_DROP);
     305         613 :   vec_validate (rt->sparse_index_by_next_index, PPP_INPUT_NEXT_PUNT);
     306         613 :   rt->sparse_index_by_next_index[PPP_INPUT_NEXT_DROP]
     307         613 :     = SPARSE_VEC_INVALID_INDEX;
     308         613 :   rt->sparse_index_by_next_index[PPP_INPUT_NEXT_PUNT]
     309         613 :     = SPARSE_VEC_INVALID_INDEX;
     310             : 
     311         613 :   return 0;
     312             : }
     313             : 
     314             : static void
     315         559 : ppp_setup_node (vlib_main_t *vm, u32 node_index)
     316             : {
     317         559 :   vlib_node_t *n = vlib_get_node (vm, node_index);
     318         559 :   pg_node_t *pn = pg_get_node (node_index);
     319             : 
     320         559 :   n->format_buffer = format_ppp_header_with_length;
     321         559 :   n->unformat_buffer = unformat_ppp_header;
     322         559 :   pn->unformat_edit = unformat_pg_ppp_header;
     323         559 : }
     324             : 
     325             : static clib_error_t *
     326         559 : ppp_input_init (vlib_main_t * vm)
     327             : {
     328             : 
     329             :   {
     330         559 :     clib_error_t *error = vlib_call_init_function (vm, ppp_init);
     331         559 :     if (error)
     332           0 :       clib_error_report (error);
     333             :   }
     334             : 
     335         559 :   ppp_setup_node (vm, ppp_input_node.index);
     336         559 :   ppp_input_runtime_init (vm);
     337             : 
     338         559 :   return 0;
     339             : }
     340             : 
     341       26319 : VLIB_INIT_FUNCTION (ppp_input_init);
     342        1679 : VLIB_WORKER_INIT_FUNCTION (ppp_input_runtime_init);
     343             : 
     344             : void
     345        1677 : ppp_register_input_protocol (vlib_main_t * vm,
     346             :                              ppp_protocol_t protocol, u32 node_index)
     347             : {
     348        1677 :   ppp_main_t *em = &ppp_main;
     349             :   ppp_protocol_info_t *pi;
     350             :   ppp_input_runtime_t *rt;
     351             :   u16 *n;
     352             :   u32 i;
     353             : 
     354             :   {
     355        1677 :     clib_error_t *error = vlib_call_init_function (vm, ppp_input_init);
     356        1677 :     if (error)
     357           0 :       clib_error_report (error);
     358             :   }
     359             : 
     360        1677 :   pi = ppp_get_protocol_info (em, protocol);
     361        1677 :   pi->node_index = node_index;
     362        1677 :   pi->next_index = vlib_node_add_next (vm, ppp_input_node.index, node_index);
     363             : 
     364             :   /* Setup ppp protocol -> next index sparse vector mapping. */
     365        1677 :   rt = vlib_node_get_runtime_data (vm, ppp_input_node.index);
     366        1677 :   n =
     367        1677 :     sparse_vec_validate (rt->next_by_protocol,
     368             :                          clib_host_to_net_u16 (protocol));
     369        1677 :   n[0] = pi->next_index;
     370             : 
     371             :   /* Rebuild next index -> sparse index inverse mapping when sparse vector
     372             :      is updated. */
     373        1677 :   vec_validate (rt->sparse_index_by_next_index, pi->next_index);
     374        5031 :   for (i = 1; i < vec_len (rt->next_by_protocol); i++)
     375        3354 :     rt->sparse_index_by_next_index[rt->next_by_protocol[i]] = i;
     376        1677 : }
     377             : 
     378             : /*
     379             :  * fd.io coding-style-patch-verification: ON
     380             :  *
     381             :  * Local Variables:
     382             :  * eval: (c-set-style "gnu")
     383             :  * End:
     384             :  */

Generated by: LCOV version 1.14