LCOV - code coverage report
Current view: top level - vnet/bier - bier_input.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 39 42 92.9 %
Date: 2023-07-05 22:20:52 Functions: 5 5 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2016 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 <vnet/buffer.h>
      17             : 
      18             : #include <vnet/bier/bier_table.h>
      19             : #include <vnet/bier/bier_hdr_inlines.h>
      20             : 
      21             : typedef enum {
      22             : #define bier_error(n,s) BIER_INPUT_ERROR_##n,
      23             : #include <vnet/bier/bier_input_error.def>
      24             : #undef bier_error
      25             :     BIER_INPUT_N_ERROR,
      26             : } bier_input_error_t;
      27             : 
      28             : static char * bier_error_strings[] = {
      29             : #define bier_error(n,s) s,
      30             : #include <vnet/bier/bier_input_error.def>
      31             : #undef bier_error
      32             : };
      33             : 
      34             : typedef enum bier_input_next_t_ {
      35             :     BIER_INPUT_NEXT_BIER_LOOKUP,
      36             :     BIER_INPUT_NEXT_DROP,
      37             :     BIER_INPUT_N_NEXT,
      38             : } bier_input_next_t;
      39             : 
      40             : vlib_node_registration_t bier_input_node;
      41             : 
      42             : /**
      43             :  * @brief Packet trace record for BIER input
      44             :  */
      45             : typedef struct bier_input_trace_t_
      46             : {
      47             :     u32 next_index;
      48             :     u32 bt_index;
      49             : } bier_input_trace_t;
      50             : 
      51             : static int
      52        1173 : bier_hdr_validate (bier_hdr_t *bier_hdr,
      53             :                    bier_hdr_len_id_t expected_length)
      54             : {
      55             :     /*
      56             :      * checks:
      57             :      *  - the version field must be 1
      58             :      *  - the header length matches the length expected
      59             :      */
      60        1173 :     if (PREDICT_FALSE((BIER_HDR_VERSION_1 != bier_hdr_get_version(bier_hdr)) ||
      61             :                       (expected_length != bier_hdr_get_len_id(bier_hdr)))) {
      62           0 :         return (0);
      63             :     }
      64             : 
      65        1173 :     return (1);
      66             : }
      67             : 
      68             : static uword
      69          20 : bier_input (vlib_main_t * vm,
      70             :             vlib_node_runtime_t * node,
      71             :             vlib_frame_t * from_frame)
      72             : {
      73             :     u32 n_left_from, next_index, * from, * to_next;
      74             : 
      75          20 :     from = vlib_frame_vector_args (from_frame);
      76          20 :     n_left_from = from_frame->n_vectors;
      77             : 
      78             :     /*
      79             :      * objection your honour! speculation!
      80             :      */
      81          20 :     next_index = node->cached_next_index;
      82             : 
      83          40 :     while (n_left_from > 0)
      84             :     {
      85             :         u32 n_left_to_next;
      86             : 
      87          20 :         vlib_get_next_frame (vm, node, next_index,
      88             :                              to_next, n_left_to_next);
      89             : 
      90        1193 :         while (n_left_from > 0 && n_left_to_next > 0)
      91             :         {
      92             :             const bier_table_t *bt0;
      93             :             vlib_buffer_t * b0;
      94             :             bier_hdr_t * bh0;
      95             :             u32 bi0, next0;
      96             :             u32 bt_index0;
      97             : 
      98        1173 :             bi0 = from[0];
      99        1173 :             to_next[0] = bi0;
     100        1173 :             from += 1;
     101        1173 :             to_next += 1;
     102        1173 :             n_left_from -= 1;
     103        1173 :             n_left_to_next -= 1;
     104             : 
     105        1173 :             b0 = vlib_get_buffer (vm, bi0);
     106        1173 :             bh0 = vlib_buffer_get_current (b0);
     107        1173 :             bier_hdr_ntoh(bh0);
     108             : 
     109             :             /*
     110             :              * In the MPLS decap node we squirrelled away the
     111             :              * index for the BIER table as the tx adjacency
     112             :              */
     113        1173 :             bt_index0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
     114        1173 :             bt0 = bier_table_get(bt_index0);
     115             : 
     116        1173 :             if (PREDICT_TRUE(bier_hdr_validate(bh0, bt0->bt_id.bti_hdr_len)))
     117             :             {
     118        1173 :                 next0 = BIER_INPUT_NEXT_BIER_LOOKUP;
     119             :             } else {
     120           0 :                 next0 = BIER_INPUT_NEXT_DROP;
     121           0 :                 b0->error = node->errors[BIER_INPUT_ERROR_INVALID_HEADER];
     122             :             }
     123             : 
     124        1173 :             if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
     125             :             {
     126             :                 bier_input_trace_t *tr;
     127             : 
     128        1173 :                 tr = vlib_add_trace (vm, node, b0, sizeof (*tr));
     129        1173 :                 tr->next_index = next0;
     130        1173 :                 tr->bt_index = bt_index0;
     131             :             }
     132             : 
     133        1173 :             vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
     134             :                                              to_next, n_left_to_next,
     135             :                                              bi0, next0);
     136             :         }
     137             : 
     138          20 :         vlib_put_next_frame (vm, node, next_index, n_left_to_next);
     139             :     }
     140             : 
     141          20 :     vlib_node_increment_counter (vm, bier_input_node.index,
     142             :                                  BIER_INPUT_ERROR_PKTS_VALID,
     143          20 :                                  from_frame->n_vectors);
     144          20 :     return (from_frame->n_vectors);
     145             : }
     146             : 
     147             : static u8 *
     148         636 : format_bier_input_trace (u8 * s, va_list * args)
     149             : {
     150         636 :     CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
     151         636 :     CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
     152         636 :     bier_input_trace_t * t = va_arg (*args, bier_input_trace_t *);
     153             : 
     154         636 :     s = format (s, " next [%d], BIER Table index %d",
     155             :                 t->next_index, t->bt_index);
     156         636 :     return s;
     157             : }
     158             : 
     159      178120 : VLIB_REGISTER_NODE (bier_input_node) = {
     160             :     .function = bier_input,
     161             :     .name = "bier-input",
     162             :     /* Takes a vector of packets. */
     163             :     .vector_size = sizeof (u32),
     164             : 
     165             :     .n_errors = BIER_INPUT_N_ERROR,
     166             :     .error_strings = bier_error_strings,
     167             : 
     168             :     .n_next_nodes = BIER_INPUT_N_NEXT,
     169             :     .next_nodes = {
     170             :         [BIER_INPUT_NEXT_BIER_LOOKUP] = "bier-lookup",
     171             :         [BIER_INPUT_NEXT_DROP] = "bier-drop",
     172             :     },
     173             : 
     174             :     .format_trace = format_bier_input_trace,
     175             : };

Generated by: LCOV version 1.14