LCOV - code coverage report
Current view: top level - vnet/bier - bier_output.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 48 48 100.0 %
Date: 2023-10-26 01:39:38 Functions: 4 4 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_fmask.h>
      19             : #include <vnet/bier/bier_hdr_inlines.h>
      20             : #include <vlib/vlib.h>
      21             : 
      22             : static char * bier_output_error_strings[] = {
      23             : #define bier_error(n,s) s,
      24             : #include <vnet/bier/bier_output_error.def>
      25             : #undef bier_error
      26             : };
      27             : 
      28             : /*
      29             :  * Keep these values semantically the same as BIER output
      30             :  */
      31             : #define foreach_bier_output_next                \
      32             :     _(DROP, "bier-drop")
      33             : 
      34             : typedef enum {
      35             : #define _(s,n) BIER_OUTPUT_NEXT_##s,
      36             :     foreach_bier_output_next
      37             : #undef _
      38             :     BIER_OUTPUT_N_NEXT,
      39             : } bier_output_next_t;
      40             : 
      41             : typedef enum {
      42             : #define bier_error(n,s) BIER_OUTPUT_ERROR_##n,
      43             : #include <vnet/bier/bier_output_error.def>
      44             : #undef bier_error
      45             :     BIER_OUTPUT_N_ERROR,
      46             : } bier_output_error_t;
      47             : 
      48             : /**
      49             :  * Forward declaration
      50             :  */
      51             : vlib_node_registration_t bier_output_node;
      52             : extern vlib_combined_counter_main_t bier_fmask_counters;
      53             : 
      54             : /**
      55             :  * @brief Packet trace record for a BIER output
      56             :  */
      57             : typedef struct bier_output_trace_t_
      58             : {
      59             :     u32 next_index;
      60             :     index_t bfm_index;
      61             :     mpls_label_t bfm_label;
      62             : } bier_output_trace_t;
      63             : 
      64             : static uword
      65          17 : bier_output (vlib_main_t * vm,
      66             :              vlib_node_runtime_t * node,
      67             :              vlib_frame_t * from_frame)
      68             : {
      69          17 :   vlib_combined_counter_main_t *cm = &bier_fmask_counters;
      70             :     u32 n_left_from, next_index, * from, * to_next;
      71             :     u32 thread_index;
      72             : 
      73          17 :     thread_index = vm->thread_index;
      74          17 :     from = vlib_frame_vector_args (from_frame);
      75          17 :     n_left_from = from_frame->n_vectors;
      76             : 
      77             :     /*
      78             :      * objection your honour! speculation!
      79             :      */
      80          17 :     next_index = node->cached_next_index;
      81             : 
      82          34 :     while (n_left_from > 0)
      83             :     {
      84             :         u32 n_left_to_next;
      85             : 
      86          17 :         vlib_get_next_frame (vm, node, next_index,
      87             :                              to_next, n_left_to_next);
      88             : 
      89        1059 :         while (n_left_from > 0 && n_left_to_next > 0)
      90             :         {
      91             :             bier_output_next_t next0;
      92             :             bier_bit_string_t bbs;
      93             :             vlib_buffer_t * b0;
      94             :             bier_fmask_t *bfm0;
      95             :             mpls_label_t *h0;
      96             :             bier_hdr_t *bh0;
      97             :             u32 bfmi0;
      98             :             u32 bi0;
      99             : 
     100        1042 :             bi0 = from[0];
     101        1042 :             to_next[0] = bi0;
     102        1042 :             from += 1;
     103        1042 :             to_next += 1;
     104        1042 :             n_left_from -= 1;
     105        1042 :             n_left_to_next -= 1;
     106             : 
     107        1042 :             b0 = vlib_get_buffer (vm, bi0);
     108        1042 :             bh0 = vlib_buffer_get_current (b0);
     109        1042 :             bier_bit_string_init_from_hdr(bh0, &bbs);
     110             : 
     111             :             /*
     112             :              * In the BIER Lookup node we squirrelled away the
     113             :              * BIER fmask index as the adj index
     114             :              */
     115        1042 :             bfmi0 = vnet_buffer (b0)->ip.adj_index[VLIB_TX];
     116        1042 :             bfm0 = bier_fmask_get(bfmi0);
     117             : 
     118        1042 :             vlib_increment_combined_counter(
     119             :                 cm, thread_index, bfmi0, 1,
     120             :                 vlib_buffer_length_in_chain (vm, b0));
     121             : 
     122             :             /*
     123             :              * perform the logical AND of the packet's mask with
     124             :              * that of the fmask objects, to reset the bits that
     125             :              * are only on the shortest path the the fmask NH.
     126             :              */
     127        1042 :             bier_bit_string_logical_and_string(
     128        1042 :                 &bfm0->bfm_bits.bfmb_input_reset_string,
     129             :                 &bbs);
     130             : 
     131             :             /*
     132             :              * this is the last time we touch the BIER header
     133             :              * so flip to network order
     134             :              */
     135        1042 :             bier_hdr_hton(bh0);
     136             : 
     137             :             /*
     138             :              * paint the BIER peer's label
     139             :              */
     140        1042 :             if (!(bfm0->bfm_flags & BIER_FMASK_FLAG_DISP))
     141             :             {
     142             :                 /*
     143             :                  * since a BIFT value and a MPLS label are formated the
     144             :                  * same, this painting works OK.
     145             :                  */
     146         902 :                 vlib_buffer_advance(b0, -(word)sizeof(mpls_label_t));
     147         902 :                 h0 = vlib_buffer_get_current(b0);
     148             :                 
     149         902 :                 h0[0] = bfm0->bfm_label;
     150             : 
     151         902 :                 ((char*)h0)[3]= vnet_buffer(b0)->mpls.ttl - 1;
     152             :             }
     153             : 
     154             :             /*
     155             :              * setup next graph node
     156             :              */
     157        1042 :             next0 = bfm0->bfm_dpo.dpoi_next_node;
     158        1042 :             vnet_buffer(b0)->ip.adj_index[VLIB_TX] = bfm0->bfm_dpo.dpoi_index;
     159             : 
     160        1042 :             if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
     161             :             {
     162             :                 bier_output_trace_t *tr;
     163             : 
     164        1042 :                 tr = vlib_add_trace (vm, node, b0, sizeof (*tr));
     165        1042 :                 tr->next_index = next0;
     166        1042 :                 tr->bfm_index = bfmi0;
     167        1042 :                 tr->bfm_label = bfm0->bfm_label;
     168             :             }
     169             : 
     170        1042 :             vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
     171             :                                              to_next, n_left_to_next,
     172             :                                              bi0, next0);
     173             :         }
     174             : 
     175          17 :         vlib_put_next_frame (vm, node, next_index, n_left_to_next);
     176             :     }
     177             : 
     178          17 :     vlib_node_increment_counter (vm, bier_output_node.index,
     179             :                                  BIER_OUTPUT_ERROR_NONE,
     180          17 :                                  from_frame->n_vectors);
     181          17 :     return (from_frame->n_vectors);
     182             : }
     183             : 
     184             : static u8 *
     185         392 : format_bier_output_trace (u8 * s, va_list * args)
     186             : {
     187         392 :     CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
     188         392 :     CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
     189         392 :     bier_output_trace_t * t = va_arg (*args, bier_output_trace_t *);
     190             : 
     191         392 :     s = format (s, " next [%d], BFM index %d label:%x",
     192             :                 t->next_index, t->bfm_index, t->bfm_label);
     193         392 :     return s;
     194             : }
     195             : 
     196      183788 : VLIB_REGISTER_NODE (bier_output_node) = {
     197             :     .function = bier_output,
     198             :     .name = "bier-output",
     199             :     /* Takes a vector of packets. */
     200             :     .vector_size = sizeof (u32),
     201             : 
     202             :     .n_errors = BIER_OUTPUT_N_ERROR,
     203             :     .error_strings = bier_output_error_strings,
     204             : 
     205             :     .n_next_nodes = BIER_OUTPUT_N_NEXT,
     206             :     .next_nodes = {
     207             :         [BIER_OUTPUT_NEXT_DROP] = "bier-drop",
     208             :     },
     209             : 
     210             :     .format_trace = format_bier_output_trace,
     211             : };

Generated by: LCOV version 1.14