LCOV - code coverage report
Current view: top level - vnet/llc - node.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 67 121 55.4 %
Date: 2023-10-26 01:39:38 Functions: 9 9 100.0 %

          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             :  * llc_node.c: llc 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/llc/llc.h>
      43             : 
      44             : #define foreach_llc_input_next                  \
      45             :   _ (PUNT, "error-punt")                      \
      46             :   _ (DROP, "error-drop")
      47             : 
      48             : typedef enum
      49             : {
      50             : #define _(s,n) LLC_INPUT_NEXT_##s,
      51             :   foreach_llc_input_next
      52             : #undef _
      53             :     LLC_INPUT_N_NEXT,
      54             : } llc_input_next_t;
      55             : 
      56             : typedef struct
      57             : {
      58             :   u8 packet_data[32];
      59             : } llc_input_trace_t;
      60             : 
      61             : static u8 *
      62           4 : format_llc_input_trace (u8 * s, va_list * va)
      63             : {
      64           4 :   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *);
      65           4 :   CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *);
      66           4 :   llc_input_trace_t *t = va_arg (*va, llc_input_trace_t *);
      67             : 
      68           4 :   s = format (s, "%U", format_llc_header, t->packet_data);
      69             : 
      70           4 :   return s;
      71             : }
      72             : 
      73             : static uword
      74           4 : llc_input (vlib_main_t * vm,
      75             :            vlib_node_runtime_t * node, vlib_frame_t * from_frame)
      76             : {
      77           4 :   llc_main_t *lm = &llc_main;
      78             :   u32 n_left_from, next_index, *from, *to_next;
      79             : 
      80           4 :   from = vlib_frame_vector_args (from_frame);
      81           4 :   n_left_from = from_frame->n_vectors;
      82             : 
      83           4 :   if (node->flags & VLIB_NODE_FLAG_TRACE)
      84           4 :     vlib_trace_frame_buffers_only (vm, node,
      85             :                                    from,
      86             :                                    n_left_from,
      87             :                                    sizeof (from[0]),
      88             :                                    sizeof (llc_input_trace_t));
      89             : 
      90           4 :   next_index = node->cached_next_index;
      91             : 
      92           8 :   while (n_left_from > 0)
      93             :     {
      94             :       u32 n_left_to_next;
      95             : 
      96           4 :       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
      97             : 
      98           4 :       while (n_left_from >= 4 && n_left_to_next >= 2)
      99             :         {
     100             :           u32 bi0, bi1;
     101             :           vlib_buffer_t *b0, *b1;
     102             :           llc_header_t *h0, *h1;
     103             :           u8 next0, next1, len0, len1, enqueue_code;
     104             : 
     105             :           /* Prefetch next iteration. */
     106             :           {
     107             :             vlib_buffer_t *b2, *b3;
     108             : 
     109           0 :             b2 = vlib_get_buffer (vm, from[2]);
     110           0 :             b3 = vlib_get_buffer (vm, from[3]);
     111             : 
     112           0 :             vlib_prefetch_buffer_header (b2, LOAD);
     113           0 :             vlib_prefetch_buffer_header (b3, LOAD);
     114             : 
     115           0 :             CLIB_PREFETCH (b2->data, sizeof (h0[0]), LOAD);
     116           0 :             CLIB_PREFETCH (b3->data, sizeof (h1[0]), LOAD);
     117             :           }
     118             : 
     119           0 :           bi0 = from[0];
     120           0 :           bi1 = from[1];
     121           0 :           to_next[0] = bi0;
     122           0 :           to_next[1] = bi1;
     123           0 :           from += 2;
     124           0 :           to_next += 2;
     125           0 :           n_left_to_next -= 2;
     126           0 :           n_left_from -= 2;
     127             : 
     128           0 :           b0 = vlib_get_buffer (vm, bi0);
     129           0 :           b1 = vlib_get_buffer (vm, bi1);
     130             : 
     131           0 :           h0 = vlib_buffer_get_current (b0);
     132           0 :           h1 = vlib_buffer_get_current (b1);
     133             : 
     134           0 :           len0 = llc_header_length (h0);
     135           0 :           len1 = llc_header_length (h1);
     136             : 
     137           0 :           vlib_buffer_advance (b0, len0);
     138           0 :           vlib_buffer_advance (b1, len1);
     139             : 
     140           0 :           next0 = lm->input_next_by_protocol[h0->dst_sap];
     141           0 :           next1 = lm->input_next_by_protocol[h1->dst_sap];
     142             : 
     143           0 :           b0->error =
     144           0 :             node->errors[next0 ==
     145             :                          LLC_INPUT_NEXT_DROP ? LLC_ERROR_UNKNOWN_PROTOCOL :
     146             :                          LLC_ERROR_NONE];
     147           0 :           b1->error =
     148           0 :             node->errors[next1 ==
     149             :                          LLC_INPUT_NEXT_DROP ? LLC_ERROR_UNKNOWN_PROTOCOL :
     150             :                          LLC_ERROR_NONE];
     151             : 
     152           0 :           enqueue_code = (next0 != next_index) + 2 * (next1 != next_index);
     153             : 
     154           0 :           if (PREDICT_FALSE (enqueue_code != 0))
     155             :             {
     156           0 :               switch (enqueue_code)
     157             :                 {
     158           0 :                 case 1:
     159             :                   /* A B A */
     160           0 :                   to_next[-2] = bi1;
     161           0 :                   to_next -= 1;
     162           0 :                   n_left_to_next += 1;
     163           0 :                   vlib_set_next_frame_buffer (vm, node, next0, bi0);
     164           0 :                   break;
     165             : 
     166           0 :                 case 2:
     167             :                   /* A A B */
     168           0 :                   to_next -= 1;
     169           0 :                   n_left_to_next += 1;
     170           0 :                   vlib_set_next_frame_buffer (vm, node, next1, bi1);
     171           0 :                   break;
     172             : 
     173           0 :                 case 3:
     174             :                   /* A B B or A B C */
     175           0 :                   to_next -= 2;
     176           0 :                   n_left_to_next += 2;
     177           0 :                   vlib_set_next_frame_buffer (vm, node, next0, bi0);
     178           0 :                   vlib_set_next_frame_buffer (vm, node, next1, bi1);
     179           0 :                   if (next0 == next1)
     180             :                     {
     181           0 :                       vlib_put_next_frame (vm, node, next_index,
     182             :                                            n_left_to_next);
     183           0 :                       next_index = next1;
     184           0 :                       vlib_get_next_frame (vm, node, next_index, to_next,
     185             :                                            n_left_to_next);
     186             :                     }
     187             :                 }
     188             :             }
     189             :         }
     190             : 
     191           8 :       while (n_left_from > 0 && n_left_to_next > 0)
     192             :         {
     193             :           u32 bi0;
     194             :           vlib_buffer_t *b0;
     195             :           llc_header_t *h0;
     196             :           u8 next0, len0;
     197             : 
     198           4 :           bi0 = from[0];
     199           4 :           to_next[0] = bi0;
     200           4 :           from += 1;
     201           4 :           to_next += 1;
     202           4 :           n_left_from -= 1;
     203           4 :           n_left_to_next -= 1;
     204             : 
     205           4 :           b0 = vlib_get_buffer (vm, bi0);
     206             : 
     207           4 :           h0 = vlib_buffer_get_current (b0);
     208             : 
     209           4 :           len0 = llc_header_length (h0);
     210             : 
     211           4 :           vlib_buffer_advance (b0, len0);
     212             : 
     213           4 :           next0 = lm->input_next_by_protocol[h0->dst_sap];
     214             : 
     215           4 :           b0->error =
     216           4 :             node->errors[next0 ==
     217             :                          LLC_INPUT_NEXT_DROP ? LLC_ERROR_UNKNOWN_PROTOCOL :
     218             :                          LLC_ERROR_NONE];
     219             : 
     220             :           /* Sent packet to wrong next? */
     221           4 :           if (PREDICT_FALSE (next0 != next_index))
     222             :             {
     223             :               /* Return old frame; remove incorrectly enqueued packet. */
     224           2 :               vlib_put_next_frame (vm, node, next_index, n_left_to_next + 1);
     225             : 
     226             :               /* Send to correct next. */
     227           2 :               next_index = next0;
     228           2 :               vlib_get_next_frame (vm, node, next_index,
     229             :                                    to_next, n_left_to_next);
     230             : 
     231           2 :               to_next[0] = bi0;
     232           2 :               to_next += 1;
     233           2 :               n_left_to_next -= 1;
     234             :             }
     235             :         }
     236             : 
     237           4 :       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
     238             :     }
     239             : 
     240           4 :   return from_frame->n_vectors;
     241             : }
     242             : 
     243             : static char *llc_error_strings[] = {
     244             : #define _(f,s) s,
     245             :   foreach_llc_error
     246             : #undef _
     247             : };
     248             : 
     249             : /* *INDENT-OFF* */
     250      183788 : VLIB_REGISTER_NODE (llc_input_node) = {
     251             :   .function = llc_input,
     252             :   .name = "llc-input",
     253             :   /* Takes a vector of packets. */
     254             :   .vector_size = sizeof (u32),
     255             : 
     256             :   .n_errors = LLC_N_ERROR,
     257             :   .error_strings = llc_error_strings,
     258             : 
     259             :   .n_next_nodes = LLC_INPUT_N_NEXT,
     260             :   .next_nodes = {
     261             : #define _(s,n) [LLC_INPUT_NEXT_##s] = n,
     262             :     foreach_llc_input_next
     263             : #undef _
     264             :   },
     265             : 
     266             :   .format_buffer = format_llc_header_with_length,
     267             :   .format_trace = format_llc_input_trace,
     268             :   .unformat_buffer = unformat_llc_header,
     269             : };
     270             : /* *INDENT-ON* */
     271             : 
     272             : static void
     273         575 : llc_setup_node (vlib_main_t *vm, u32 node_index)
     274             : {
     275         575 :   vlib_node_t *n = vlib_get_node (vm, node_index);
     276         575 :   pg_node_t *pn = pg_get_node (node_index);
     277             : 
     278         575 :   n->format_buffer = format_llc_header_with_length;
     279         575 :   n->unformat_buffer = unformat_llc_header;
     280         575 :   pn->unformat_edit = unformat_pg_llc_header;
     281         575 : }
     282             : 
     283             : static clib_error_t *
     284         575 : llc_input_init (vlib_main_t * vm)
     285             : {
     286         575 :   llc_main_t *lm = &llc_main;
     287             : 
     288             :   {
     289         575 :     clib_error_t *error = vlib_call_init_function (vm, llc_init);
     290         575 :     if (error)
     291           0 :       clib_error_report (error);
     292             :   }
     293             : 
     294         575 :   llc_setup_node (vm, llc_input_node.index);
     295             : 
     296             :   {
     297             :     int i;
     298      147775 :     for (i = 0; i < ARRAY_LEN (lm->input_next_by_protocol); i++)
     299      147200 :       lm->input_next_by_protocol[i] = LLC_INPUT_NEXT_DROP;
     300             :   }
     301             : 
     302         575 :   return 0;
     303             : }
     304             : 
     305       29375 : VLIB_INIT_FUNCTION (llc_input_init);
     306             : 
     307             : void
     308        3450 : llc_register_input_protocol (vlib_main_t * vm,
     309             :                              llc_protocol_t protocol, u32 node_index)
     310             : {
     311        3450 :   llc_main_t *lm = &llc_main;
     312             :   llc_protocol_info_t *pi;
     313             : 
     314             :   {
     315        3450 :     clib_error_t *error = vlib_call_init_function (vm, llc_input_init);
     316        3450 :     if (error)
     317           0 :       clib_error_report (error);
     318             :     /* Otherwise, osi_input_init will wipe out e.g. the snap init */
     319        3450 :     error = vlib_call_init_function (vm, osi_input_init);
     320        3450 :     if (error)
     321           0 :       clib_error_report (error);
     322             :   }
     323             : 
     324        3450 :   pi = llc_get_protocol_info (lm, protocol);
     325        3450 :   pi->node_index = node_index;
     326        3450 :   pi->next_index = vlib_node_add_next (vm, llc_input_node.index, node_index);
     327             : 
     328        3450 :   lm->input_next_by_protocol[protocol] = pi->next_index;
     329        3450 : }
     330             : 
     331             : /*
     332             :  * fd.io coding-style-patch-verification: ON
     333             :  *
     334             :  * Local Variables:
     335             :  * eval: (c-set-style "gnu")
     336             :  * End:
     337             :  */

Generated by: LCOV version 1.14